26 #ifndef OOMPH_TRIANGLE_MESH_TEMPLATE_CC
27 #define OOMPH_TRIANGLE_MESH_TEMPLATE_CC
32 #include "../generic/map_matrix.h"
33 #include "../generic/multi_domain.h"
34 #include "../generic/projection.h"
35 #include "../generic/face_element_as_geometric_object.h"
44 template<
class ELEMENT>
46 const bool &use_attributes)
49 MeshChecker::assert_geometric_element<TElementGeometricBase,ELEMENT>(2);
52 unsigned nelem = Tmp_mesh_pt->nelement();
53 Element_pt.resize(nelem);
56 unsigned nnode_scaffold = Tmp_mesh_pt->nnode();
60 std::map<Node*, unsigned> old_global_number;
63 for (
unsigned inod = 0; inod < nnode_scaffold; inod++)
65 Node* old_node_pt = Tmp_mesh_pt->node_pt(inod);
66 old_global_number[old_node_pt] = inod;
70 Oomph_vertex_nodes_id.resize(nnode_scaffold);
73 Node_pt.resize(nnode_scaffold, 0);
76 unsigned nbound = Tmp_mesh_pt->nboundary();
79 set_nboundary(nbound);
80 Boundary_element_pt.resize(nbound);
81 Face_index_at_boundary.resize(nbound);
87 Boundary_region_element_pt.resize(nbound);
88 Face_index_region_at_boundary.resize(nbound);
92 for (
unsigned e = 0; e < nelem; e++)
94 Element_pt[e] =
new ELEMENT;
98 unsigned nnod_el = Tmp_mesh_pt->finite_element_pt(0)->nnode();
103 std::map<Node*, unsigned> global_number;
104 unsigned global_count = 0;
107 std::map<double, Vector<FiniteElement*> > element_attribute_map;
114 element_attribute_map[0].resize(0);
118 for (
unsigned e = 0; e < nelem; e++)
121 for (
unsigned j = 0; j < nnod_el; j++)
124 Node* scaffold_node_pt = Tmp_mesh_pt->finite_element_pt(e)->node_pt(j);
128 unsigned j_global = global_number[scaffold_node_pt];
134 Oomph_vertex_nodes_id[global_count] =
135 old_global_number[scaffold_node_pt];
139 std::set<unsigned>* boundaries_pt;
140 scaffold_node_pt->get_boundaries_pt(boundaries_pt);
143 Node* new_node_pt = 0;
146 if (boundaries_pt != 0)
150 finite_element_pt(e)->construct_boundary_node(j,time_stepper_pt);
153 for (std::set<unsigned>::iterator it = boundaries_pt->begin(); it
154 != boundaries_pt->end(); ++it)
156 add_boundary_node(*it, new_node_pt);
163 new_node_pt = finite_element_pt(e)->construct_node(j,time_stepper_pt);
170 global_number[scaffold_node_pt] = global_count;
176 Node_pt[global_count - 1] = new_node_pt;
179 for (
unsigned i = 0; i < finite_element_pt(e)->dim(); i++)
181 new_node_pt->x(i) = scaffold_node_pt->x(i);
187 finite_element_pt(e)->node_pt(j) = Node_pt[j_global - 1];
194 element_attribute_map[Tmp_mesh_pt->element_attribute(e)].push_back(
195 finite_element_pt(e));
203 unsigned n_attribute = element_attribute_map.size();
206 this->Region_attribute.resize(n_attribute);
210 for (std::map<
double, Vector<FiniteElement*> >::iterator it =
211 element_attribute_map.begin(); it!=element_attribute_map.end(); ++it)
213 this->Region_attribute[count] = it->first;
214 Region_element_pt[
static_cast<unsigned>(Region_attribute[count])] =
225 unsigned boundary_id=0;
229 unsigned n_node_1d = finite_element_pt(0)->nnode_1d();
230 unsigned dim = finite_element_pt(0)->dim();
233 Vector<double>
s(dim);
236 unsigned n_node = finite_element_pt(0)->nnode();
239 unsigned n_global_edge = Tmp_mesh_pt->nglobal_edge();
240 Vector < Vector<Node*> > nodes_on_global_edge(n_global_edge);
243 for (
unsigned e = 0; e < nelem; e++)
246 FiniteElement*
const elem_pt = finite_element_pt(e);
247 FiniteElement*
const tmp_elem_pt = Tmp_mesh_pt->finite_element_pt(e);
250 unsigned n_edge_node = 3 * (n_node_1d - 1);
254 for (
unsigned n = n_edge_node; n < n_node; ++n)
257 Node* new_node_pt = elem_pt->construct_node(n, time_stepper_pt);
260 elem_pt->local_coordinate_of_node(n,
s);
264 for (
unsigned i = 0; i < dim; i++)
266 new_node_pt->x(i) = tmp_elem_pt->interpolated_x(
s, i);
270 Node_pt.push_back(new_node_pt);
278 for (
unsigned j = 0; j < 3; j++)
281 boundary_id = Tmp_mesh_pt->edge_boundary(e, j);
284 unsigned edge_index = Tmp_mesh_pt->edge_index(e, j);
287 if (nodes_on_global_edge[edge_index].size() == 0)
290 for (
unsigned j2 = 0; j2 < n_node_1d - 2; ++j2)
293 Node* new_node_pt = 0;
298 new_node_pt = elem_pt->construct_boundary_node(n, time_stepper_pt);
300 this->add_boundary_node(boundary_id - 1, new_node_pt);
305 new_node_pt = elem_pt->construct_node(n, time_stepper_pt);
309 elem_pt->local_coordinate_of_node(n,
s);
313 for (
unsigned i = 0; i < dim; i++)
315 new_node_pt->x(i) = tmp_elem_pt->interpolated_x(
s, i);
319 Node_pt.push_back(new_node_pt);
322 nodes_on_global_edge[edge_index].push_back(new_node_pt);
334 for (
unsigned j2 = 0; j2 < n_node_1d - 2; ++j2)
338 elem_pt->node_pt(n) = nodes_on_global_edge[edge_index][n_node_1d - 3
348 Boundary_element_pt[boundary_id - 1].push_back(elem_pt);
351 Face_index_at_boundary[boundary_id - 1].push_back((j + 2) % 3);
356 unsigned tmp_region =
357 static_cast<unsigned> (Tmp_mesh_pt->element_attribute(e));
359 Boundary_region_element_pt[boundary_id - 1]
360 [tmp_region].push_back(elem_pt);
363 Face_index_region_at_boundary[boundary_id - 1]
364 [tmp_region].push_back((j + 2) % 3);
373 Lookup_for_elements_next_boundary_is_setup =
true;
384 template<
class ELEMENT>
394 Vector<FiniteElement*> face_el_pt;
401 unsigned n_repeated_ele = 0;
403 const unsigned n_regions = this->nregion();
407 std::map<FiniteElement*,FiniteElement*> face_to_bulk_element_pt;
410 Vector<std::pair<Node*, Node*> > done_nodes_pt;
416 for (
unsigned rr = 0 ; rr < n_regions; rr++)
418 const unsigned region_id =
419 static_cast<unsigned>(this->Region_attribute[rr]);
422 const unsigned nel_in_region =
423 this->nboundary_element_in_region(b, region_id);
425 unsigned nel_repetead_in_region = 0;
429 if (nel_in_region > 0)
433 bool repeated =
false;
436 for (
unsigned e = 0; e < nel_in_region; e++)
439 FiniteElement* bulk_elem_pt =
440 this->boundary_element_in_region_pt(b, region_id, e);
444 if (this->is_mesh_distributed() && bulk_elem_pt->is_halo())
455 this->face_index_at_boundary_in_region(b,region_id,e);
460 FiniteElement* tmp_ele_pt =
461 new DummyFaceElement<ELEMENT>(bulk_elem_pt, face_index);
463 const unsigned n_nodes = tmp_ele_pt->nnode();
465 std::pair<Node*, Node*> tmp_pair =
466 std::make_pair(tmp_ele_pt->node_pt(0),
467 tmp_ele_pt->node_pt(n_nodes - 1));
469 std::pair<Node*, Node*> tmp_pair_inverse =
470 std::make_pair(tmp_ele_pt->node_pt(n_nodes - 1),
471 tmp_ele_pt->node_pt(0));
474 const unsigned n_done_nodes = done_nodes_pt.size();
475 for (
unsigned l = 0; l < n_done_nodes; l++)
477 if (tmp_pair == done_nodes_pt[l] ||
478 tmp_pair_inverse == done_nodes_pt[l])
480 nel_repetead_in_region++;
490 done_nodes_pt.push_back(tmp_pair);
492 face_el_pt.push_back(tmp_ele_pt);
494 face_to_bulk_element_pt[tmp_ele_pt] = bulk_elem_pt;
508 nele += nel_in_region;
510 n_repeated_ele += nel_repetead_in_region;
519 nele = this->nboundary_element(b);
526 bool repeated =
false;
529 for (
unsigned e = 0; e < nele; e++)
532 FiniteElement* bulk_elem_pt = this->boundary_element_pt(b, e);
536 if (this->is_mesh_distributed() && bulk_elem_pt->is_halo())
546 int face_index = this->face_index_at_boundary(b, e);
551 FiniteElement* tmp_ele_pt =
552 new DummyFaceElement<ELEMENT>(bulk_elem_pt, face_index);
554 const unsigned n_nodes = tmp_ele_pt->nnode();
556 std::pair<Node*, Node*> tmp_pair =
557 std::make_pair(tmp_ele_pt->node_pt(0),
558 tmp_ele_pt->node_pt(n_nodes - 1));
560 std::pair<Node*, Node*> tmp_pair_inverse =
561 std::make_pair(tmp_ele_pt->node_pt(n_nodes - 1),
562 tmp_ele_pt->node_pt(0));
565 const unsigned n_done_nodes = done_nodes_pt.size();
566 for (
unsigned l = 0; l < n_done_nodes; l++)
568 if (tmp_pair == done_nodes_pt[l] ||
569 tmp_pair_inverse == done_nodes_pt[l])
583 done_nodes_pt.push_back(tmp_pair);
585 face_el_pt.push_back(tmp_ele_pt);
587 face_to_bulk_element_pt[tmp_ele_pt] = bulk_elem_pt;
605 nele-= n_repeated_ele;
608 if (nele!=face_el_pt.size())
610 std::ostringstream error_message;
612 <<
"The independent counting of face elements ("<<nele<<
") for "
613 <<
"boundary ("<<b<<
") is different\n"
614 <<
"from the real number of face elements in the container ("
615 << face_el_pt.size() <<
")\n";
616 throw OomphLibError(error_message.str(),
617 "TriangleMesh::identify_boundary_segments_and_assign_initial_zeta_values()",
618 OOMPH_EXCEPTION_LOCATION);
631 std::vector<bool> is_halo_face_element(nele,
false);
634 unsigned nnon_halo_face_elements = 0;
637 for (
unsigned ie = 0; ie < nele; ie++)
640 FiniteElement* face_ele_pt = face_el_pt[ie];
642 FiniteElement* tmp_bulk_ele_pt = face_to_bulk_element_pt[face_ele_pt];
644 if (!tmp_bulk_ele_pt->is_halo())
646 is_halo_face_element[ie] =
false;
647 nnon_halo_face_elements++;
652 is_halo_face_element[ie] =
true;
658 const unsigned nhalo_face_element = nele - nnon_halo_face_elements;
659 if (nhalo_face_element > 0)
661 std::ostringstream error_message;
663 <<
"There should not be halo face elements since they were not "
664 <<
"considered when computing the face elements\n\n"
665 <<
"The number of found halo face elements is: "
666 << nhalo_face_element <<
"\n\n";
667 throw OomphLibError(error_message.str(),
668 "TriangleMesh::identify_boundary_segments_and_assign_initial_zeta_values()",
669 OOMPH_EXCEPTION_LOCATION);
675 Vector<std::list<FiniteElement*> > segment_sorted_ele_pt;
679 unsigned nsorted_face_elements = 0;
683 std::map<FiniteElement*, bool> done_el;
687 std::map<FiniteElement*, bool> is_inverted;
690 while(nsorted_face_elements < nnon_halo_face_elements)
694 std::list<FiniteElement*> sorted_el_pt;
695 sorted_el_pt.clear();
699 bool found_initial_face_element =
false;
702 FiniteElement* ele_face_pt = 0;
705 for (iface = 0; iface < nele; iface++)
707 if (!is_halo_face_element[iface])
709 ele_face_pt = face_el_pt[iface];
711 if (!done_el[ele_face_pt])
714 found_initial_face_element =
true;
716 nsorted_face_elements++;
718 sorted_el_pt.push_back(ele_face_pt);
720 done_el[ele_face_pt] =
true;
727 if (!found_initial_face_element)
729 std::ostringstream error_message;
731 <<
"Could not find an initial face element for the current segment\n";
732 throw OomphLibError(error_message.str(),
733 "TriangleMesh::identify_boundary_segments_and_assign_initial_zeta_values()",
734 OOMPH_EXCEPTION_LOCATION);
739 const unsigned nnod = ele_face_pt->nnode();
743 Node* left_node_pt = ele_face_pt->node_pt(0);
744 Node* right_node_pt = ele_face_pt->node_pt(nnod - 1);
748 bool face_element_added =
false;
757 for (
unsigned iiface = iface; iiface < nele; iiface++)
760 face_element_added =
false;
763 ele_face_pt = face_el_pt[iiface];
767 if (!(done_el[ele_face_pt] || is_halo_face_element[iiface]))
770 Node* local_left_node_pt = ele_face_pt->node_pt(0);
771 Node* local_right_node_pt = ele_face_pt->node_pt(nnod - 1);
773 if (left_node_pt == local_right_node_pt)
775 left_node_pt = local_left_node_pt;
776 sorted_el_pt.push_front(ele_face_pt);
777 is_inverted[ele_face_pt] =
false;
778 face_element_added =
true;
781 else if (left_node_pt == local_left_node_pt)
783 left_node_pt = local_right_node_pt;
784 sorted_el_pt.push_front(ele_face_pt);
785 is_inverted[ele_face_pt] =
true;
786 face_element_added =
true;
789 else if (right_node_pt == local_left_node_pt)
791 right_node_pt = local_right_node_pt;
792 sorted_el_pt.push_back(ele_face_pt);
793 is_inverted[ele_face_pt] =
false;
794 face_element_added =
true;
797 else if (right_node_pt == local_right_node_pt)
799 right_node_pt = local_left_node_pt;
800 sorted_el_pt.push_back(ele_face_pt);
801 is_inverted[ele_face_pt] =
true;
802 face_element_added =
true;
805 if (face_element_added)
807 done_el[ele_face_pt] =
true;
808 nsorted_face_elements++;
814 }
while(face_element_added &&
815 (nsorted_face_elements < nnon_halo_face_elements));
818 segment_sorted_ele_pt.push_back(sorted_el_pt);
823 const unsigned nsegments = segment_sorted_ele_pt.size();
839 Vector<std::set<Node*> > segment_all_nodes_pt;
842 Vector<double> segment_arclength(nsegments);
845 Vector<unsigned> nvertices_per_segment(nsegments);
848 Vector<double> initial_zeta_segment(nsegments);
851 Vector<double> final_zeta_segment(nsegments);
854 if (nnon_halo_face_elements > 0 && nsegments == 0)
856 std::ostringstream error_message;
858 <<
"The number of segments is zero, but the number of nonhalo\n"
859 <<
"elements is: (" << nnon_halo_face_elements <<
")\n";
860 throw OomphLibError(error_message.str(),
861 "TriangleMesh::identify_boundary_segments_and_assign_initial_zeta_values()",
862 OOMPH_EXCEPTION_LOCATION);
868 for (
unsigned is = 0;
is < nsegments;
is++)
871 if (segment_sorted_ele_pt[
is].size() == 0)
873 std::ostringstream error_message;
875 <<
"The (" <<
is <<
")-th segment has no elements\n";
876 throw OomphLibError(error_message.str(),
877 "TriangleMesh::identify_boundary_segments_and_assign_initial_zeta_values()",
878 OOMPH_EXCEPTION_LOCATION);
883 FiniteElement* first_ele_pt = segment_sorted_ele_pt[
is].front();
886 const unsigned nnod = first_ele_pt->nnode();
889 Node *first_node_pt = first_ele_pt->node_pt(0);
890 if (is_inverted[first_ele_pt])
892 first_node_pt = first_ele_pt->node_pt(nnod-1);
896 FiniteElement* last_ele_pt = segment_sorted_ele_pt[
is].back();
899 Node *last_node_pt = last_ele_pt->node_pt(nnod-1);
900 if (is_inverted[last_ele_pt])
902 last_node_pt = last_ele_pt->node_pt(0);
906 double x_left = first_node_pt->x(0);
907 double y_left = first_node_pt->x(1);
911 Vector<double> zeta(1, 0.0);
916 if (this->boundary_geom_object_pt(b)!=0)
918 first_node_pt->get_coordinates_on_boundary(b, zeta);
919 initial_zeta_segment[
is] = zeta[0];
920 last_node_pt->get_coordinates_on_boundary(b, zeta);
921 final_zeta_segment[
is] = zeta[0];
925 std::set<Node*> local_nodes_pt;
926 local_nodes_pt.insert(first_node_pt);
929 for (std::list<FiniteElement*>::iterator it =
930 segment_sorted_ele_pt[
is].begin();
931 it != segment_sorted_ele_pt[
is].end(); it++)
934 FiniteElement* el_pt = *it;
939 if (is_inverted[el_pt])
946 for (
unsigned j = 1; j < nnod; j++)
948 Node* nod_pt = el_pt->node_pt(k_nod);
952 double x_right = nod_pt->x(0);
953 double y_right = nod_pt->x(1);
957 (x_right - x_left) * (x_right - x_left) + (y_right - y_left)
958 * (y_right - y_left));
975 local_nodes_pt.insert(nod_pt);
981 segment_arclength[
is] = zeta[0];
984 nvertices_per_segment[
is] = local_nodes_pt.size();
987 segment_all_nodes_pt.push_back(local_nodes_pt);
993 if (segment_all_nodes_pt.size() != nsegments)
995 std::ostringstream error_message;
997 <<
"The number of segments ("<<nsegments<<
") and the number of "
998 <<
"sets of nodes ("<<segment_all_nodes_pt.size()<<
") representing\n"
999 <<
"the\nsegments is different!!!\n\n";
1000 throw OomphLibError(
1001 error_message.str(),
1002 OOMPH_CURRENT_FUNCTION,
1003 OOMPH_EXCEPTION_LOCATION);
1010 Vector<double> initial_segment_arclength(nsegments,0.0);
1014 Vector<unsigned> current_segment_to_original_segment_index(nsegments);
1018 Vector<unsigned> segment_inverted(nsegments);
1031 const unsigned nsegments_initial_coordinates =
1032 original_mesh_pt->boundary_segment_initial_coordinate(b).size();
1034 const unsigned nsegments_final_coordinates =
1035 original_mesh_pt->boundary_segment_final_coordinate(b).size();
1037 if (nsegments_initial_coordinates!=nsegments_final_coordinates)
1039 std::stringstream error_message;
1041 <<
"The number of segments that present initial coordinates "
1042 <<nsegments_initial_coordinates<<
" is different from "
1043 <<
"the\nnumber of segments that present final coordinates "
1044 <<nsegments_final_coordinates<<
"\n\n";
1045 throw OomphLibError(
1046 error_message.str(),
1047 OOMPH_CURRENT_FUNCTION,
1048 OOMPH_EXCEPTION_LOCATION);
1053 if (nsegments_initial_coordinates != nsegments)
1055 std::stringstream error_message;
1057 <<
"Working with boundary ("<< b <<
").\n The number of initial and "
1058 <<
"final coordinates ("
1059 <<nsegments_initial_coordinates<<
") is different from\n"
1060 <<
"the number of found segments ("<< nsegments <<
").\n\n";
1061 throw OomphLibError(
1062 error_message.str(),
1063 OOMPH_CURRENT_FUNCTION,
1064 OOMPH_EXCEPTION_LOCATION);
1070 Vector<Vector<double> >original_mesh_segment_initial_coordinate(nsegments);
1071 Vector<Vector<double> >original_mesh_segment_final_coordinate(nsegments);
1073 Vector<double> original_mesh_segment_initial_zeta(nsegments);
1074 Vector<double> original_mesh_segment_final_zeta(nsegments);
1076 Vector<double> original_mesh_segment_initial_arclength(nsegments);
1077 Vector<double> original_mesh_segment_final_arclength(nsegments);
1079 for (
unsigned is = 0;
is < nsegments;
is++)
1081 original_mesh_segment_initial_coordinate[
is].resize(2);
1082 original_mesh_segment_final_coordinate[
is].resize(2);
1083 for (
unsigned k = 0; k < 2; k++)
1085 original_mesh_segment_initial_coordinate[
is][k] =
1086 original_mesh_pt->boundary_segment_initial_coordinate(b)[
is][k];
1087 original_mesh_segment_final_coordinate[
is][k] =
1088 original_mesh_pt->boundary_segment_final_coordinate(b)[
is][k];
1091 if (this->boundary_geom_object_pt(b)!=0)
1093 original_mesh_segment_initial_zeta[
is] =
1094 original_mesh_pt->boundary_segment_initial_zeta(b)[
is];
1095 original_mesh_segment_final_zeta[
is] =
1096 original_mesh_pt->boundary_segment_final_zeta(b)[
is];
1100 original_mesh_segment_initial_arclength[
is] =
1101 original_mesh_pt->boundary_segment_initial_arclength(b)[
is];
1102 original_mesh_segment_final_arclength[
is] =
1103 original_mesh_pt->boundary_segment_final_arclength(b)[
is];
1108 Boundary_segment_inverted[b].clear();
1109 Boundary_segment_initial_coordinate[b].clear();
1110 Boundary_segment_final_coordinate[b].clear();
1112 Boundary_segment_initial_zeta[b].clear();
1113 Boundary_segment_final_zeta[b].clear();
1115 Boundary_segment_initial_arclength[b].clear();
1116 Boundary_segment_final_arclength[b].clear();
1122 std::map<unsigned,bool> segment_done;
1123 for (
unsigned is = 0;
is < nsegments;
is++)
1127 bool found_original_segment =
false;
1131 Vector<double> current_seg_initial_coord(2);
1132 Vector<double> current_seg_final_coord(2);
1135 FiniteElement* current_seg_initial_ele_pt =
1136 segment_sorted_ele_pt[
is].front();
1139 const unsigned nnod = current_seg_initial_ele_pt->nnode();
1142 Node *current_seg_first_node_pt=
1143 current_seg_initial_ele_pt->node_pt(0);
1144 if (is_inverted[current_seg_initial_ele_pt])
1146 current_seg_first_node_pt =
1147 current_seg_initial_ele_pt->node_pt(nnod-1);
1151 FiniteElement* current_seg_last_ele_pt =
1152 segment_sorted_ele_pt[
is].back();
1155 Node *current_seg_last_node_pt =
1156 current_seg_last_ele_pt->node_pt(nnod-1);
1157 if (is_inverted[current_seg_last_ele_pt])
1159 current_seg_last_node_pt =
1160 current_seg_last_ele_pt->node_pt(0);
1164 for (
unsigned i = 0; i < 2; i++)
1166 current_seg_initial_coord[i]=current_seg_first_node_pt->x(i);
1167 current_seg_final_coord[i]=current_seg_last_node_pt->x(i);
1174 for (
unsigned orig_s = 0; orig_s < nsegments; orig_s++)
1176 if (!segment_done[orig_s])
1179 Vector<double> initial_coordinate =
1180 original_mesh_segment_initial_coordinate[orig_s];
1181 Vector<double> final_coordinate =
1182 original_mesh_segment_final_coordinate[orig_s];
1187 ((current_seg_initial_coord[0] - initial_coordinate[0])*
1188 (current_seg_initial_coord[0] - initial_coordinate[0]))
1190 ((current_seg_initial_coord[1] - initial_coordinate[1])*
1191 (current_seg_initial_coord[1] - initial_coordinate[1]));
1196 ToleranceForVertexMismatchInPolygons::Tolerable_error)
1201 ((current_seg_final_coord[0] - final_coordinate[0])*
1202 (current_seg_final_coord[0] - final_coordinate[0]))
1204 ((current_seg_final_coord[1] - final_coordinate[1])*
1205 (current_seg_final_coord[1] - final_coordinate[1]));
1211 ToleranceForVertexMismatchInPolygons::Tolerable_error)
1215 current_segment_to_original_segment_index[
is] = orig_s;
1218 Boundary_segment_inverted[b].push_back(0);
1221 Boundary_segment_initial_coordinate[b].push_back(
1222 initial_coordinate);
1223 Boundary_segment_final_coordinate[b].push_back(
1227 if (this->boundary_geom_object_pt(b)!=0)
1230 Boundary_segment_initial_zeta[b].push_back(
1231 original_mesh_segment_initial_zeta[orig_s]);
1232 Boundary_segment_final_zeta[b].push_back(
1233 original_mesh_segment_final_zeta[orig_s]);
1239 Boundary_segment_initial_arclength[b].push_back(
1240 original_mesh_segment_initial_arclength[orig_s]);
1241 Boundary_segment_final_arclength[b].push_back(
1242 original_mesh_segment_final_arclength[orig_s]);
1245 segment_done[orig_s] =
true;
1247 found_original_segment =
true;
1259 ((current_seg_initial_coord[0] - final_coordinate[0])*
1260 (current_seg_initial_coord[0] - final_coordinate[0]))
1262 ((current_seg_initial_coord[1] - final_coordinate[1])*
1263 (current_seg_initial_coord[1] - final_coordinate[1]));
1264 dist_inv = sqrt(dist_inv);
1269 ToleranceForVertexMismatchInPolygons::Tolerable_error)
1274 ((current_seg_final_coord[0] - initial_coordinate[0])*
1275 (current_seg_final_coord[0] - initial_coordinate[0]))
1277 ((current_seg_final_coord[1] - initial_coordinate[1])*
1278 (current_seg_final_coord[1] - initial_coordinate[1]));
1279 dist_inv = sqrt(dist_inv);
1284 ToleranceForVertexMismatchInPolygons::Tolerable_error)
1288 current_segment_to_original_segment_index[
is] = orig_s;
1291 Boundary_segment_inverted[b].push_back(1);
1294 Boundary_segment_initial_coordinate[b].push_back(
1295 initial_coordinate);
1296 Boundary_segment_final_coordinate[b].push_back(
1300 if (this->boundary_geom_object_pt(b)!=0)
1303 Boundary_segment_initial_zeta[b].push_back(
1304 original_mesh_segment_initial_zeta[orig_s]);
1305 Boundary_segment_final_zeta[b].push_back(
1306 original_mesh_segment_final_zeta[orig_s]);
1311 Boundary_segment_initial_arclength[b].push_back(
1312 original_mesh_segment_initial_arclength[orig_s]);
1313 Boundary_segment_final_arclength[b].push_back(
1314 original_mesh_segment_final_arclength[orig_s]);
1317 segment_done[orig_s] =
true;
1319 found_original_segment =
true;
1334 if (!found_original_segment)
1336 std::stringstream error_message;
1338 <<
"The ("<<
is<<
")-th segment on the current segment was not\n"
1339 <<
"found when trying to identify it with the original mesh's\n"
1340 <<
"segment coordinates\n";
1341 throw OomphLibError(error_message.str(),
1342 OOMPH_CURRENT_FUNCTION,
1343 OOMPH_EXCEPTION_LOCATION);
1364 if (
this != original_mesh_pt)
1370 Vector<double> first_node_zeta_coordinate =
1371 original_mesh_pt->boundary_initial_zeta_coordinate(b);
1372 Vector<double> last_node_zeta_coordinate =
1373 original_mesh_pt->boundary_final_zeta_coordinate(b);
1377 const double boundary_arclength =
1378 std::max(first_node_zeta_coordinate[0],
1379 last_node_zeta_coordinate[0]);
1381 for (
unsigned is = 0;
is < nsegments;
is++)
1386 if (boundary_geom_object_pt(b)==0)
1403 FiniteElement* first_ele_pt=segment_sorted_ele_pt[
is].front();
1406 const unsigned nnod = first_ele_pt->nnode();
1409 Node *first_node_pt = first_ele_pt->node_pt(0);
1410 if (is_inverted[first_ele_pt])
1412 first_node_pt = first_ele_pt->node_pt(nnod-1);
1416 FiniteElement* last_ele_pt=segment_sorted_ele_pt[
is].back();
1419 Node *last_node_pt = last_ele_pt->node_pt(nnod-1);
1420 if (is_inverted[last_ele_pt])
1422 last_node_pt = last_ele_pt->node_pt(0);
1426 Vector<double> current_segment_initial_arclen(1);
1427 Vector<double> current_segment_final_arclen(1);
1429 if (!Boundary_segment_inverted[b][
is])
1432 get_coordinates_on_boundary(b, current_segment_initial_arclen);
1434 get_coordinates_on_boundary(b, current_segment_final_arclen);
1439 get_coordinates_on_boundary(b, current_segment_final_arclen);
1441 get_coordinates_on_boundary(b, current_segment_initial_arclen);
1449 bool increasing_order =
false;
1453 if (current_segment_initial_arclen[0] <
1454 current_segment_final_arclen[0])
1456 increasing_order =
true;
1460 else if (current_segment_initial_arclen[0] >
1461 current_segment_final_arclen[0])
1463 increasing_order =
false;
1468 std::stringstream error_message;
1470 <<
"It was not possible to identify if the zeta values on "
1471 <<
"boundary ("<<b<<
")\nand segment ("<<
is<<
") should go in "
1472 <<
"increasing or decreasing order.\n--- New mesh ---\n"
1473 <<
"Current segment initial arclength: ("
1474 << current_segment_initial_arclen[0]<<
")\n"
1475 <<
"First node coordinates: ("
1476 << first_node_pt->x(0) <<
", " << first_node_pt->x(1) <<
")\n"
1477 <<
"Current segment final arclength: ("
1478 << current_segment_final_arclen[0]<<
")\n"
1479 <<
"Last node coordinates: ("
1480 << last_node_pt->x(0) <<
", " << last_node_pt->x(1) <<
")\n"
1481 <<
"Current segment arclength: ("
1482 << segment_arclength[
is] <<
")\n";
1483 throw OomphLibError(error_message.str(),
1484 OOMPH_CURRENT_FUNCTION,
1485 OOMPH_EXCEPTION_LOCATION);
1491 const unsigned prev_s =
1492 current_segment_to_original_segment_index[
is];
1493 const double original_segment_initial_arclength =
1494 original_mesh_pt->boundary_segment_initial_arclength(b)[prev_s];
1495 const double original_segment_final_arclength =
1496 original_mesh_pt->boundary_segment_final_arclength(b)[prev_s];
1500 bool original_increasing_order =
false;
1505 double starting_arclength = 0.0;
1506 if (original_segment_final_arclength >
1507 original_segment_initial_arclength)
1510 original_increasing_order =
true;
1512 starting_arclength = original_segment_initial_arclength;
1514 else if (original_segment_final_arclength <
1515 original_segment_initial_arclength)
1518 original_increasing_order =
false;
1520 starting_arclength = original_segment_final_arclength;
1525 std::stringstream error_message;
1527 <<
"It was not possible to identify if the zeta values on "
1528 <<
"boundary ("<<b<<
")\nand segment ("<<
is<<
") should go in "
1529 <<
"increasing or decreasing order.\n--- Original mesh ---\n"
1530 <<
"Original segment initial arclength: ("
1531 << original_segment_initial_arclength<<
")\n"
1532 <<
"Original segment final arclength: ("
1533 << original_segment_final_arclength<<
")\n";
1534 throw OomphLibError(error_message.str(),
1535 OOMPH_CURRENT_FUNCTION,
1536 OOMPH_EXCEPTION_LOCATION);
1543 if (increasing_order && original_increasing_order)
1559 std::set<Node*> seg_nodes_pt = segment_all_nodes_pt[
is];
1562 for (std::set<Node*>::iterator it = seg_nodes_pt.begin();
1563 it != seg_nodes_pt.end(); it++)
1566 Vector<double> zeta(1);
1568 Node* nod_pt = (*it);
1570 nod_pt->get_coordinates_on_boundary(b, zeta);
1573 starting_arclength + (zeta[0] * segment_arclength[
is]);
1575 zeta[0] = temp / boundary_arclength;
1577 if (std::fabs(zeta[0] - 1.0) < 1.0e-14)
1581 else if (std::fabs(zeta[0]) < 1.0e-14)
1587 nod_pt->set_coordinates_on_boundary(b, zeta);
1590 else if (!increasing_order && original_increasing_order)
1606 std::set<Node*> seg_nodes_pt = segment_all_nodes_pt[
is];
1609 for (std::set<Node*>::iterator it = seg_nodes_pt.begin();
1610 it != seg_nodes_pt.end(); it++)
1613 Vector<double> zeta(1);
1615 Node* nod_pt = (*it);
1617 nod_pt->get_coordinates_on_boundary(b, zeta);
1620 starting_arclength + ((1.0 - zeta[0]) * segment_arclength[
is]);
1622 zeta[0] = temp / boundary_arclength;
1624 if (std::fabs(zeta[0] - 1.0) < 1.0e-14)
1628 else if (std::fabs(zeta[0]) < 1.0e-14)
1633 nod_pt->set_coordinates_on_boundary(b, zeta);
1636 else if (increasing_order && !original_increasing_order)
1652 std::set<Node*> seg_nodes_pt = segment_all_nodes_pt[
is];
1655 for (std::set<Node*>::iterator it = seg_nodes_pt.begin();
1656 it != seg_nodes_pt.end(); it++)
1659 Vector<double> zeta(1);
1661 Node* nod_pt = (*it);
1663 nod_pt->get_coordinates_on_boundary(b, zeta);
1666 starting_arclength + ((1.0 - zeta[0]) * segment_arclength[
is]);
1668 zeta[0] = temp / boundary_arclength;
1670 if (std::fabs(zeta[0] - 1.0) < 1.0e-14)
1674 else if (std::fabs(zeta[0]) < 1.0e-14)
1679 nod_pt->set_coordinates_on_boundary(b, zeta);
1682 else if (!increasing_order && !original_increasing_order)
1698 std::set<Node*> seg_nodes_pt = segment_all_nodes_pt[
is];
1701 for (std::set<Node*>::iterator it = seg_nodes_pt.begin();
1702 it != seg_nodes_pt.end(); it++)
1705 Vector<double> zeta(1);
1707 Node* nod_pt = (*it);
1709 nod_pt->get_coordinates_on_boundary(b, zeta);
1712 starting_arclength + (zeta[0] * segment_arclength[
is]);
1714 zeta[0] = temp / boundary_arclength;
1716 if (std::fabs(zeta[0] - 1.0) < 1.0e-14)
1720 else if (std::fabs(zeta[0]) < 1.0e-14)
1725 nod_pt->set_coordinates_on_boundary(b, zeta);
1732 for (std::list<FiniteElement*>::iterator it_list =
1733 segment_sorted_ele_pt[
is].begin();
1734 it_list != segment_sorted_ele_pt[
is].end();
1738 const unsigned nnod = (*it_list)->nnode();
1741 Node *first_node_pt = (*it_list)->node_pt(0);
1742 if(is_inverted[(*it_list)])
1744 first_node_pt = (*it_list)->node_pt(nnod-1);
1748 Node *last_node_pt = (*it_list)->node_pt(nnod-1);
1749 if(is_inverted[(*it_list)])
1751 last_node_pt = (*it_list)->node_pt(0);
1755 Vector<double> zeta(1);
1756 first_node_pt->get_coordinates_on_boundary(b, zeta);
1757 if (zeta[0] < 0.0 || zeta[0] > 1.0)
1759 std::ostringstream error_message;
1761 <<
"The boundary coordinate of the first node on boundary ("
1762 << b <<
")\nand segment (" <<
is <<
") is out of the "
1763 <<
"allowed values [0,1]\n"
1764 <<
"The node boundary coordinate: (" << zeta[0] <<
")\n"
1765 <<
"The vertex coordinates are: ("
1766 << first_node_pt->x(0) <<
", " << first_node_pt->x(1) <<
")\n";
1767 throw OomphLibError(error_message.str(),
1768 OOMPH_CURRENT_FUNCTION,
1769 OOMPH_EXCEPTION_LOCATION);
1773 last_node_pt->get_coordinates_on_boundary(b, zeta);
1774 if (zeta[0] < 0.0 || zeta[0] > 1.0)
1776 std::ostringstream error_message;
1778 <<
"The boundary coordinate of the last node on boundary ("
1779 << b <<
")\nand segment (" <<
is <<
") is out of the "
1780 <<
"allowed values [0,1]\n"
1781 <<
"The node boundary coordinate: (" << zeta[0] <<
")\n"
1782 <<
"The vertex coordinates are: ("
1783 << last_node_pt->x(0) <<
", " << last_node_pt->x(1) <<
")\n";
1784 throw OomphLibError(error_message.str(),
1785 OOMPH_CURRENT_FUNCTION,
1786 OOMPH_EXCEPTION_LOCATION);
1789 #endif // #ifdef PARANOID
1805 Boundary_initial_coordinate[b] =
1806 original_mesh_pt->boundary_initial_coordinate(b);
1808 Boundary_final_coordinate[b] =
1809 original_mesh_pt->boundary_final_coordinate(b);
1813 Boundary_initial_zeta_coordinate[b] =
1814 original_mesh_pt->boundary_initial_zeta_coordinate(b);
1816 Boundary_final_zeta_coordinate[b] =
1817 original_mesh_pt->boundary_final_zeta_coordinate(b);
1823 Assigned_segments_initial_zeta_values[b] =
true;
1826 for (
unsigned i = 0; i < nele; i++)
1828 delete face_el_pt[i];
1840 template<
class ELEMENT>
1850 OomphCommunicator* comm_pt = this->communicator_pt();
1853 const unsigned nproc = comm_pt->nproc();
1855 const unsigned my_rank = comm_pt->my_rank();
1858 Vector<FiniteElement*> all_face_ele_pt;
1863 bool is_internal_boundary =
false;
1867 std::map<FiniteElement*,FiniteElement*> face_to_bulk_element_pt;
1871 select_boundary_face_elements(all_face_ele_pt, b, is_internal_boundary,
1872 face_to_bulk_element_pt);
1875 const unsigned n_all_face_ele = all_face_ele_pt.size();
1883 std::vector<bool> is_halo_face_element(n_all_face_ele,
false);
1886 unsigned nnon_halo_face_elements = 0;
1890 for (
unsigned ie = 0; ie < n_all_face_ele; ie++)
1892 FiniteElement* face_ele_pt = all_face_ele_pt[ie];
1894 FiniteElement* tmp_bulk_ele_pt = face_to_bulk_element_pt[face_ele_pt];
1896 if (!tmp_bulk_ele_pt->is_halo())
1899 is_halo_face_element[ie] =
false;
1901 nnon_halo_face_elements++;
1906 is_halo_face_element[ie] =
true;
1912 const unsigned nhalo_face_element = n_all_face_ele - nnon_halo_face_elements;
1916 Vector<std::list<FiniteElement*> > segment_sorted_ele_pt;
1920 unsigned nsorted_face_elements = 0;
1924 std::map<FiniteElement*, bool> done_el;
1928 std::map<FiniteElement*, bool> is_inverted;
1931 while(nsorted_face_elements < nnon_halo_face_elements)
1935 std::list<FiniteElement*> sorted_el_pt;
1936 sorted_el_pt.clear();
1941 bool found_initial_face_element =
false;
1944 FiniteElement* ele_face_pt = 0;
1947 for (iface = 0; iface < n_all_face_ele; iface++)
1949 if (!is_halo_face_element[iface])
1951 ele_face_pt = all_face_ele_pt[iface];
1953 if (!done_el[ele_face_pt])
1956 found_initial_face_element =
true;
1958 nsorted_face_elements++;
1960 sorted_el_pt.push_back(ele_face_pt);
1962 done_el[ele_face_pt] =
true;
1969 if (!found_initial_face_element)
1971 std::ostringstream error_message;
1973 <<
"Could not find an initial face element for the current segment\n";
1975 throw OomphLibError(error_message.str(),
1976 OOMPH_CURRENT_FUNCTION,
1977 OOMPH_EXCEPTION_LOCATION);
1982 const unsigned nnod = ele_face_pt->nnode();
1986 Node* left_node_pt = ele_face_pt->node_pt(0);
1987 Node* right_node_pt = ele_face_pt->node_pt(nnod - 1);
1991 bool face_element_added =
false;
2000 for (
unsigned iiface = iface; iiface < n_all_face_ele; iiface++)
2003 face_element_added =
false;
2006 ele_face_pt = all_face_ele_pt[iiface];
2010 if (!(done_el[ele_face_pt] || is_halo_face_element[iiface]))
2013 Node* local_left_node_pt = ele_face_pt->node_pt(0);
2014 Node* local_right_node_pt = ele_face_pt->node_pt(nnod - 1);
2017 if (left_node_pt == local_right_node_pt)
2019 left_node_pt = local_left_node_pt;
2020 sorted_el_pt.push_front(ele_face_pt);
2021 is_inverted[ele_face_pt] =
false;
2022 face_element_added =
true;
2025 else if (left_node_pt == local_left_node_pt)
2027 left_node_pt = local_right_node_pt;
2028 sorted_el_pt.push_front(ele_face_pt);
2029 is_inverted[ele_face_pt] =
true;
2030 face_element_added =
true;
2033 else if (right_node_pt == local_left_node_pt)
2035 right_node_pt = local_right_node_pt;
2036 sorted_el_pt.push_back(ele_face_pt);
2037 is_inverted[ele_face_pt] =
false;
2038 face_element_added =
true;
2041 else if (right_node_pt == local_right_node_pt)
2043 right_node_pt = local_left_node_pt;
2044 sorted_el_pt.push_back(ele_face_pt);
2045 is_inverted[ele_face_pt] =
true;
2046 face_element_added =
true;
2049 if (face_element_added)
2051 done_el[ele_face_pt] =
true;
2052 nsorted_face_elements++;
2058 }
while(face_element_added &&
2059 (nsorted_face_elements < nnon_halo_face_elements));
2062 segment_sorted_ele_pt.push_back(sorted_el_pt);
2076 Vector<std::set<Node*> > segment_all_nodes_pt;
2079 const unsigned nsegments = segment_sorted_ele_pt.size();
2083 if (nnon_halo_face_elements > 0 && nsegments == 0)
2085 std::ostringstream error_message;
2087 <<
"The number of segments is zero, but the number of nonhalo\n"
2088 <<
"elements is: (" << nnon_halo_face_elements <<
")\n";
2089 throw OomphLibError(error_message.str(),
2090 OOMPH_CURRENT_FUNCTION,
2091 OOMPH_EXCEPTION_LOCATION);
2096 Vector<double> segment_arclength(nsegments);
2099 Vector<unsigned> nvertices_per_segment(nsegments);
2102 Vector<double> initial_zeta_segment(nsegments);
2105 Vector<double> final_zeta_segment(nsegments);
2110 for (
unsigned is = 0;
is < nsegments;
is++)
2113 if (segment_sorted_ele_pt[
is].size() == 0)
2115 std::ostringstream error_message;
2117 <<
"The (" <<
is <<
")-th segment has no elements\n";
2118 throw OomphLibError(error_message.str(),
2119 OOMPH_CURRENT_FUNCTION,
2120 OOMPH_EXCEPTION_LOCATION);
2125 FiniteElement* first_ele_pt = segment_sorted_ele_pt[
is].front();
2128 const unsigned nnod = first_ele_pt->nnode();
2131 Node *first_node_pt = first_ele_pt->node_pt(0);
2132 if (is_inverted[first_ele_pt])
2134 first_node_pt = first_ele_pt->node_pt(nnod-1);
2138 double x_left = first_node_pt->x(0);
2139 double y_left = first_node_pt->x(1);
2143 Vector<double> zeta(1, 0.0);
2148 if (this->boundary_geom_object_pt(b)!=0)
2151 first_node_pt->get_coordinates_on_boundary(b, zeta);
2153 initial_zeta_segment[
is] = zeta[0];
2156 FiniteElement* last_ele_pt = segment_sorted_ele_pt[
is].back();
2159 Node *last_node_pt = last_ele_pt->node_pt(nnod-1);
2160 if (is_inverted[last_ele_pt])
2162 last_node_pt = last_ele_pt->node_pt(0);
2166 last_node_pt->get_coordinates_on_boundary(b, zeta);
2168 final_zeta_segment[
is] = zeta[0];
2174 std::set<Node*> local_nodes_pt;
2176 local_nodes_pt.insert(first_node_pt);
2179 for (std::list<FiniteElement*>::iterator it =
2180 segment_sorted_ele_pt[
is].begin();
2181 it != segment_sorted_ele_pt[
is].end(); it++)
2184 FiniteElement* el_pt = (*it);
2190 if (is_inverted[el_pt])
2197 for (
unsigned j = 1; j < nnod; j++)
2199 Node* nod_pt = el_pt->node_pt(k_nod);
2203 double x_right = nod_pt->x(0);
2204 double y_right = nod_pt->x(1);
2208 (x_right - x_left) * (x_right - x_left) + (y_right - y_left)
2209 * (y_right - y_left));
2226 local_nodes_pt.insert(nod_pt);
2235 segment_arclength[
is] = zeta[0];
2240 nvertices_per_segment[
is] = local_nodes_pt.size();
2243 segment_all_nodes_pt.push_back(local_nodes_pt);
2252 Vector<unsigned> nvertices_before_segment(nsegments,0);
2257 Vector<double> initial_segment_arclength(nsegments,0.0);
2265 unsigned proc_with_initial_seg = 0;
2266 unsigned proc_with_final_seg = 0;
2270 unsigned initial_segment = 0;
2271 unsigned final_segment = 0;
2275 Vector<unsigned> segment_inverted(nsegments);
2279 Vector<std::list<FiniteElement*> > segment_sorted_nonhalo_ele_pt(nsegments);
2280 for (
unsigned is = 0;
is < nsegments;
is++)
2282 for (std::list<FiniteElement*>::iterator it_seg =
2283 segment_sorted_ele_pt[
is].begin();
2284 it_seg != segment_sorted_ele_pt[
is].end();
2287 segment_sorted_nonhalo_ele_pt[
is].push_back((*it_seg));
2294 for (
unsigned is = 0;
is < nsegments;
is++)
2297 FiniteElement* first_ele_pt = segment_sorted_ele_pt[
is].front();
2300 const unsigned nnod = first_ele_pt->nnode();
2303 Node *first_node_pt = first_ele_pt->node_pt(0);
2304 if (is_inverted[first_ele_pt])
2306 first_node_pt = first_ele_pt->node_pt(nnod-1);
2310 FiniteElement* last_ele_pt = segment_sorted_ele_pt[
is].back();
2313 Node *last_node_pt = last_ele_pt->node_pt(nnod-1);
2314 if (is_inverted[last_ele_pt])
2316 last_node_pt = last_ele_pt->node_pt(0);
2323 bool attached_left_halo =
false;
2324 bool attached_right_halo =
false;
2325 if (nhalo_face_element > 0)
2327 for (
unsigned iiface = 0; iiface < n_all_face_ele; iiface++)
2330 FiniteElement* halo_face_ele_pt = all_face_ele_pt[iiface];
2343 if (is_halo_face_element[iiface])
2346 Node* left_node_pt = halo_face_ele_pt->node_pt(0);
2347 Node* right_node_pt = halo_face_ele_pt->node_pt(nnod-1);
2349 if (!attached_left_halo && (first_node_pt == right_node_pt ||
2350 first_node_pt == left_node_pt))
2353 segment_sorted_ele_pt[
is].push_front(halo_face_ele_pt);
2357 attached_left_halo =
true;
2360 else if (!attached_right_halo && (last_node_pt == left_node_pt ||
2361 last_node_pt == right_node_pt))
2364 segment_sorted_ele_pt[
is].push_back(halo_face_ele_pt);
2367 attached_right_halo =
true;
2371 if (attached_left_halo && attached_right_halo)
2393 Vector<unsigned> left_processor_plus_one(nsegments);
2398 Vector<unsigned> right_processor_plus_one(nsegments);
2403 Vector<unsigned> left_halo_element(nsegments);
2408 Vector<unsigned> right_halo_element(nsegments);
2413 Vector<unsigned> left_haloed_element(nsegments);
2418 Vector<unsigned> right_haloed_element(nsegments);
2421 for (
unsigned is = 0;
is < nsegments;
is++)
2424 FiniteElement* left_face_ele_pt=segment_sorted_ele_pt[
is].front();
2428 FiniteElement* tmp_left_bulk_ele_pt =
2429 face_to_bulk_element_pt[left_face_ele_pt];
2432 if (tmp_left_bulk_ele_pt->is_halo())
2435 int left_proc = tmp_left_bulk_ele_pt->non_halo_proc_ID();
2439 std::ostringstream error_message;
2441 <<
"The current bulk element (left) is marked as halo but "
2442 <<
"the processor holding\nthe non-halo counterpart is "
2444 throw OomphLibError(error_message.str(),
2445 OOMPH_CURRENT_FUNCTION,
2446 OOMPH_EXCEPTION_LOCATION);
2450 unsigned left_processor =
static_cast<unsigned>(left_proc);
2451 left_processor_plus_one[
is] = left_processor + 1;
2454 GeneralisedElement *left_element_pt = tmp_left_bulk_ele_pt;
2457 Vector<GeneralisedElement*> left_halo_element_pt =
2458 this->halo_element_pt(left_processor);
2462 bool left_halo_element_found =
false;
2465 const unsigned n_halo_left = left_halo_element_pt.size();
2466 for (
unsigned lh = 0; lh < n_halo_left; lh++)
2468 if (left_element_pt == left_halo_element_pt[lh])
2470 left_halo_element[
is] = lh;
2472 left_halo_element_found =
true;
2479 if (!left_halo_element_found)
2481 std::ostringstream error_message;
2483 <<
"The current bulk element (left) marked as halo was "
2484 <<
"not found in the vector of halo\nelements associated "
2485 <<
"with the (" << left_processor <<
") processor.\n\n";
2486 throw OomphLibError(error_message.str(),
2487 OOMPH_CURRENT_FUNCTION,
2488 OOMPH_EXCEPTION_LOCATION);
2494 left_face_ele_pt = segment_sorted_nonhalo_ele_pt[
is].front();
2497 tmp_left_bulk_ele_pt = face_to_bulk_element_pt[left_face_ele_pt];
2501 if (tmp_left_bulk_ele_pt->is_halo())
2503 std::ostringstream error_message;
2505 <<
"The bulk element represetation of the left-most nonhalo face\n"
2506 <<
"element of the current segment ("<<
is<<
") is marked as halo,\n"
2507 <<
"but the face element created from it is nonhalo\n";
2508 throw OomphLibError(error_message.str(),
2509 OOMPH_CURRENT_FUNCTION,
2510 OOMPH_EXCEPTION_LOCATION);
2516 left_element_pt = tmp_left_bulk_ele_pt;
2520 bool left_haloed_element_found =
false;
2525 Vector<GeneralisedElement*> left_haloed_element_pt =
2526 this->haloed_element_pt(left_processor);
2528 const unsigned nhaloed_left = left_haloed_element_pt.size();
2529 for (
unsigned lhd = 0; lhd < nhaloed_left; lhd++)
2531 if (left_element_pt == left_haloed_element_pt[lhd])
2533 left_haloed_element[
is] = lhd;
2535 left_haloed_element_found =
true;
2542 if (!left_haloed_element_found)
2544 std::ostringstream error_message;
2546 <<
"The current bulk element (left) marked as haloed was "
2547 <<
"not found in the vector of haloed\nelements associated "
2548 <<
"with processor ("<< left_processor <<
").\n";
2549 throw OomphLibError(error_message.str(),
2550 OOMPH_CURRENT_FUNCTION,
2551 OOMPH_EXCEPTION_LOCATION);
2558 left_processor_plus_one[
is] = 0;
2560 left_halo_element[
is] = 0;
2562 left_haloed_element[
is] = 0;
2566 FiniteElement* right_face_ele_pt = segment_sorted_ele_pt[
is].back();
2570 FiniteElement* tmp_right_bulk_ele_pt =
2571 face_to_bulk_element_pt[right_face_ele_pt];
2574 if (tmp_right_bulk_ele_pt->is_halo())
2577 int right_proc = tmp_right_bulk_ele_pt->non_halo_proc_ID();
2581 std::ostringstream error_message;
2583 <<
"The current bulk element (right) is marked as halo but "
2584 <<
"the processor holding\nthe non-halo counterpart is "
2586 throw OomphLibError(error_message.str(),
2587 "TriangleMesh::compute_boundary_segments_connectivity_and_initial_zeta_values()",
2588 OOMPH_EXCEPTION_LOCATION);
2592 unsigned right_processor =
static_cast<unsigned>(right_proc);
2593 right_processor_plus_one[
is] = right_processor + 1;
2596 GeneralisedElement *right_element_pt = tmp_right_bulk_ele_pt;
2599 Vector<GeneralisedElement*> right_halo_element_pt =
2600 this->halo_element_pt(right_processor);
2604 bool right_halo_element_found =
false;
2607 const unsigned nhalo_right = right_halo_element_pt.size();
2608 for (
unsigned rh = 0; rh < nhalo_right; rh++)
2610 if (right_element_pt == right_halo_element_pt[rh])
2612 right_halo_element[
is] = rh;
2614 right_halo_element_found =
true;
2620 if (!right_halo_element_found)
2622 std::ostringstream error_message;
2624 <<
"The current bulk element (right) marked as halo was not "
2625 <<
"found in the vector of halo\nelements associated with "
2626 <<
"the (" << right_processor <<
") processor.\n\n";
2627 throw OomphLibError(error_message.str(),
2628 "TriangleMesh::compute_boundary_segments_connectivity_and_initial_zeta_values()",
2629 OOMPH_EXCEPTION_LOCATION);
2635 right_face_ele_pt = segment_sorted_nonhalo_ele_pt[
is].back();
2638 tmp_right_bulk_ele_pt=face_to_bulk_element_pt[right_face_ele_pt];
2641 if (tmp_right_bulk_ele_pt->is_halo())
2643 std::ostringstream error_message;
2645 <<
"The bulk element represetation of the right-most nonhalo face\n"
2646 <<
"element of the current segment ("<<
is<<
") is marked as halo,\n"
2647 <<
"but the face element created from it is nonhalo\n";
2648 throw OomphLibError(error_message.str(),
2649 "TriangleMesh::compute_boundary_segments_connectivity_and_initial_zeta_values()",
2650 OOMPH_EXCEPTION_LOCATION);
2656 right_element_pt = tmp_right_bulk_ele_pt;
2660 bool right_haloed_element_found =
false;
2664 Vector<GeneralisedElement*> right_haloed_element_pt =
2665 this->haloed_element_pt(right_processor);
2667 const unsigned nhaloed_right = right_haloed_element_pt.size();
2668 for (
unsigned rhd = 0; rhd < nhaloed_right; rhd++)
2670 if (right_element_pt == right_haloed_element_pt[rhd])
2672 right_haloed_element[
is] = rhd;
2674 right_haloed_element_found =
true;
2681 if (!right_haloed_element_found)
2683 std::ostringstream error_message;
2685 <<
"The current bulk element (right) marked as haloed was not "
2686 <<
"found in the vector of haloed\nelements associated with "
2687 <<
"the ("<< right_processor <<
") processor.\n\n";
2688 throw OomphLibError(error_message.str(),
2689 "TriangleMesh::compute_boundary_segments_connectivity_and_initial_zeta_values()",
2690 OOMPH_EXCEPTION_LOCATION);
2698 right_processor_plus_one[
is] = 0;
2700 right_halo_element[
is] = 0;
2702 right_haloed_element[
is] = 0;
2718 const unsigned root_processor = 0;
2724 Vector<unsigned> root_nsegments_per_processor(nproc);
2725 unsigned nsegments_mpi = nsegments;
2726 MPI_Gather(&nsegments_mpi, 1, MPI_UNSIGNED,
2727 &root_nsegments_per_processor[0], 1, MPI_UNSIGNED,
2728 root_processor, comm_pt->mpi_comm());
2736 const unsigned spu = 7;
2737 Vector<unsigned> flat_packed_unsigned_send_data(nsegments*spu);
2738 for (
unsigned is = 0;
is < nsegments;
is++)
2740 flat_packed_unsigned_send_data[(spu*
is)+0]=left_processor_plus_one[
is];
2741 flat_packed_unsigned_send_data[(spu*
is)+1]=right_processor_plus_one[
is];
2742 flat_packed_unsigned_send_data[(spu*
is)+2]=left_halo_element[
is];
2743 flat_packed_unsigned_send_data[(spu*
is)+3]=right_halo_element[
is];
2744 flat_packed_unsigned_send_data[(spu*
is)+4]=left_haloed_element[
is];
2745 flat_packed_unsigned_send_data[(spu*
is)+5]=right_haloed_element[
is];
2746 flat_packed_unsigned_send_data[(spu*
is)+6]=nvertices_per_segment[
is];
2750 const unsigned nudata_to_send = flat_packed_unsigned_send_data.size();
2754 Vector<int> root_nudata_to_receive(nproc,0);
2756 unsigned root_nutotal_data_receive = 0;
2757 for (
unsigned ip = 0; ip < nproc; ip++)
2761 root_nudata_to_receive[ip] = root_nsegments_per_processor[ip] * spu;
2763 root_nutotal_data_receive+= root_nudata_to_receive[ip];
2768 Vector<int> root_uoffsets_receive(nproc,0);
2769 root_uoffsets_receive[0] = 0;
2770 for (
unsigned ip = 1; ip < nproc; ip++)
2773 root_uoffsets_receive[ip] =
2774 root_uoffsets_receive[ip-1] + root_nudata_to_receive[ip-1];
2778 if (flat_packed_unsigned_send_data.size()==0)
2780 flat_packed_unsigned_send_data.resize(1);
2784 Vector<unsigned> flat_packed_unsigned_receive_data(
2785 root_nutotal_data_receive);
2786 if (my_rank!=root_processor)
2789 if (flat_packed_unsigned_receive_data.size()==0)
2791 flat_packed_unsigned_receive_data.resize(1);
2795 MPI_Gatherv(&flat_packed_unsigned_send_data[0],
2801 &flat_packed_unsigned_receive_data[0],
2806 &root_nudata_to_receive[0],
2808 &root_uoffsets_receive[0],
2813 comm_pt->mpi_comm());
2816 flat_packed_unsigned_send_data.clear();
2817 flat_packed_unsigned_send_data.resize(0);
2823 const unsigned spd = 1;
2824 Vector<double> flat_packed_double_send_data(nsegments*spd);
2825 for (
unsigned is = 0;
is < nsegments;
is++)
2827 flat_packed_double_send_data[(spd*
is)+0]=segment_arclength[
is];
2831 const unsigned nddata_to_send = flat_packed_double_send_data.size();
2834 Vector<int> root_nddata_to_receive(nproc,0);
2836 unsigned root_ndtotal_data_receive = 0;
2837 for (
unsigned ip =0; ip < nproc; ip++)
2839 root_nddata_to_receive[ip] = root_nsegments_per_processor[ip] * spd;
2840 root_ndtotal_data_receive+= root_nddata_to_receive[ip];
2845 Vector<int> root_doffsets_receive(nproc,0);
2846 root_doffsets_receive[0] = 0;
2847 for (
unsigned ip = 1; ip < nproc; ip++)
2850 root_doffsets_receive[ip] =
2851 root_doffsets_receive[ip-1] + root_nddata_to_receive[ip-1];
2855 if (flat_packed_double_send_data.size()==0)
2857 flat_packed_double_send_data.resize(1);
2861 Vector<double> flat_packed_double_receive_data(root_ndtotal_data_receive);
2862 if (my_rank!=root_processor)
2865 if (flat_packed_double_receive_data.size()==0)
2867 flat_packed_double_receive_data.resize(1);
2871 MPI_Gatherv(&flat_packed_double_send_data[0],
2877 &flat_packed_double_receive_data[0],
2881 &root_nddata_to_receive[0],
2883 &root_doffsets_receive[0],
2888 comm_pt->mpi_comm());
2891 flat_packed_double_send_data.clear();
2892 flat_packed_double_send_data.resize(0);
2900 Vector<Vector<double> > root_initial_segment_arclength(nproc);
2904 Vector<Vector<unsigned> > root_nvertices_before_segment(nproc);
2910 Vector<Vector<unsigned> > root_segment_inverted(nproc);
2914 double root_accumulated_arclength = 0.0;
2918 unsigned root_accumulated_vertices_before_segment = 0;
2922 if (my_rank == root_processor)
2932 Vector<Vector<unsigned> > root_left_processor_plus_one(nproc);
2937 Vector<Vector<unsigned> > root_right_processor_plus_one(nproc);
2942 Vector<Vector<unsigned> > root_left_halo_element(nproc);
2948 Vector<Vector<unsigned> > root_right_halo_element(nproc);
2954 Vector<Vector<unsigned> > root_left_haloed_element(nproc);
2960 Vector<Vector<unsigned> > root_right_haloed_element(nproc);
2963 Vector<Vector<unsigned> > root_nvertices_per_segment(nproc);
2966 Vector<Vector<double> > root_segment_arclength(nproc);
2968 unsigned ucounter = 0;
2969 unsigned dcounter = 0;
2970 for (
unsigned ip = 0; ip < nproc; ip++)
2973 const unsigned nsegs_iproc = root_nsegments_per_processor[ip];
2975 root_left_processor_plus_one[ip].resize(nsegs_iproc);
2976 root_right_processor_plus_one[ip].resize(nsegs_iproc);
2977 root_left_halo_element[ip].resize(nsegs_iproc);
2978 root_right_halo_element[ip].resize(nsegs_iproc);
2979 root_left_haloed_element[ip].resize(nsegs_iproc);
2980 root_right_haloed_element[ip].resize(nsegs_iproc);
2983 root_nvertices_per_segment[ip].resize(nsegs_iproc);
2984 root_segment_arclength[ip].resize(nsegs_iproc);
2985 root_segment_inverted[ip].resize(nsegs_iproc);
2989 for(
unsigned is = 0;
is < nsegs_iproc;
is++)
2992 root_left_processor_plus_one[ip][
is] =
2993 flat_packed_unsigned_receive_data[ucounter++];
2994 root_right_processor_plus_one[ip][
is] =
2995 flat_packed_unsigned_receive_data[ucounter++];
2996 root_left_halo_element[ip][
is] =
2997 flat_packed_unsigned_receive_data[ucounter++];
2998 root_right_halo_element[ip][
is] =
2999 flat_packed_unsigned_receive_data[ucounter++];
3000 root_left_haloed_element[ip][
is] =
3001 flat_packed_unsigned_receive_data[ucounter++];
3002 root_right_haloed_element[ip][
is] =
3003 flat_packed_unsigned_receive_data[ucounter++];
3004 root_nvertices_per_segment[ip][
is] =
3005 flat_packed_unsigned_receive_data[ucounter++];
3008 root_segment_arclength[ip][
is] =
3009 flat_packed_double_receive_data[dcounter++];
3018 Vector<Vector<int> > left_connected_segment_plus_one(nproc);
3019 Vector<Vector<int> > right_connected_segment_plus_one(nproc);
3020 for (
unsigned ip = 0; ip < nproc; ip++)
3022 const unsigned nsegs_iproc = root_nsegments_per_processor[ip];
3023 left_connected_segment_plus_one[ip].resize(nsegs_iproc,-1);
3024 right_connected_segment_plus_one[ip].resize(nsegs_iproc,-1);
3029 std::list<std::pair<unsigned, unsigned> > proc_seg_connectivity;
3030 proc_seg_connectivity.clear();
3033 std::map<std::pair<unsigned, unsigned>,
bool> done_segment;
3037 unsigned left_proc = 0;
3038 unsigned right_proc = 0;
3039 unsigned left_seg = 0;
3040 unsigned right_seg = 0;
3041 for (
unsigned ip = 0; ip < nproc; ip++)
3043 const unsigned nsegs_iproc = root_nsegments_per_processor[ip];
3044 if (nsegs_iproc > 0)
3046 right_proc = left_proc = ip;
3047 right_seg = left_seg = 0;
3054 std::pair<unsigned, unsigned> add_segment =
3055 std::make_pair(left_proc, left_seg);
3056 done_segment[add_segment] =
true;
3057 proc_seg_connectivity.push_back(add_segment);
3061 bool added_segment_to_the_left =
false;
3062 bool added_segment_to_the_right =
false;
3067 std::pair<unsigned, unsigned> left_pair =
3068 proc_seg_connectivity.front();
3069 left_proc = left_pair.first;
3070 left_seg = left_pair.second;
3074 const unsigned new_left_proc =
3075 root_left_processor_plus_one[left_proc][left_seg];
3077 if (new_left_proc != 0)
3080 added_segment_to_the_left =
false;
3082 const unsigned left_halo_id =
3083 root_left_halo_element[left_proc][left_seg];
3086 const unsigned left_haloed_id =
3087 root_left_haloed_element[left_proc][left_seg];
3091 const unsigned nsegs_new_left_proc =
3092 root_nsegments_per_processor[new_left_proc-1];
3094 for (
unsigned ils = 0; ils < nsegs_new_left_proc; ils++)
3096 std::pair<unsigned, unsigned> candidate_seg =
3097 std::make_pair(new_left_proc-1, ils);
3100 if (!done_segment[candidate_seg])
3104 const unsigned right_proc_of_new_left_proc =
3105 root_right_processor_plus_one[new_left_proc-1][ils];
3108 const unsigned left_proc_of_new_left_proc =
3109 root_left_processor_plus_one[new_left_proc-1][ils];
3112 if (right_proc_of_new_left_proc != 0 &&
3113 right_proc_of_new_left_proc-1 == left_proc)
3118 const unsigned right_halo_id =
3119 root_right_halo_element[new_left_proc-1][ils];
3120 const unsigned right_haloed_id =
3121 root_right_haloed_element[new_left_proc-1][ils];
3122 if (left_halo_id == right_haloed_id &&
3123 left_haloed_id == right_halo_id)
3127 left_connected_segment_plus_one[left_proc][left_seg]=
3130 proc_seg_connectivity.push_front(candidate_seg);
3131 added_segment_to_the_left =
true;
3137 if (left_proc_of_new_left_proc != 0 &&
3138 left_proc_of_new_left_proc-1 == left_proc)
3143 const unsigned inv_left_halo_id =
3144 root_left_halo_element[new_left_proc-1][ils];
3145 const unsigned inv_left_haloed_id =
3146 root_left_haloed_element[new_left_proc-1][ils];
3147 if (left_halo_id == inv_left_haloed_id &&
3148 left_haloed_id == inv_left_halo_id)
3152 left_connected_segment_plus_one[left_proc][left_seg]=
3155 proc_seg_connectivity.push_front(candidate_seg);
3159 const unsigned tmp_proc =
3160 root_left_processor_plus_one[new_left_proc-1][ils];
3161 const unsigned tmp_halo =
3162 root_left_halo_element[new_left_proc-1][ils];
3163 const unsigned tmp_haloed =
3164 root_left_haloed_element[new_left_proc-1][ils];
3166 root_left_processor_plus_one[new_left_proc-1][ils] =
3167 root_right_processor_plus_one[new_left_proc-1][ils];
3168 root_left_halo_element[new_left_proc-1][ils] =
3169 root_right_halo_element[new_left_proc-1][ils];
3170 root_left_haloed_element[new_left_proc-1][ils] =
3171 root_right_haloed_element[new_left_proc-1][ils];
3173 root_right_processor_plus_one[new_left_proc-1][ils] =
3175 root_right_halo_element[new_left_proc-1][ils]=tmp_halo;
3176 root_right_haloed_element[new_left_proc-1][ils] =
3181 root_segment_inverted[new_left_proc-1][ils] = 1;
3183 added_segment_to_the_left =
true;
3191 if (!added_segment_to_the_left)
3193 std::ostringstream error_message;
3195 <<
"The corresponding processor and segment to the left of "
3196 <<
"the current left\nmost segment was not found\n";
3197 throw OomphLibError(error_message.str(),
3198 "TriangleMesh::compute_boundary_segments_connectivity_and_initial_zeta_values()",
3199 OOMPH_EXCEPTION_LOCATION);
3206 added_segment_to_the_left =
false;
3210 std::pair<unsigned, unsigned> right_pair =
3211 proc_seg_connectivity.back();
3212 right_proc = right_pair.first;
3213 right_seg = right_pair.second;
3217 const unsigned new_right_proc =
3218 root_right_processor_plus_one[right_proc][right_seg];
3220 if (new_right_proc != 0)
3223 added_segment_to_the_right =
false;
3225 const unsigned right_halo_id =
3226 root_right_halo_element[right_proc][right_seg];
3229 const unsigned right_haloed_id =
3230 root_right_haloed_element[right_proc][right_seg];
3234 const unsigned nsegs_new_right_proc =
3235 root_nsegments_per_processor[new_right_proc-1];
3237 for (
unsigned irs = 0; irs < nsegs_new_right_proc; irs++)
3239 std::pair<unsigned, unsigned> candidate_seg =
3240 std::make_pair(new_right_proc-1, irs);
3243 if (!done_segment[candidate_seg])
3247 const unsigned left_proc_of_new_right_proc =
3248 root_left_processor_plus_one[new_right_proc-1][irs];
3251 const unsigned right_proc_of_new_right_proc =
3252 root_right_processor_plus_one[new_right_proc-1][irs];
3255 if (left_proc_of_new_right_proc != 0 &&
3256 left_proc_of_new_right_proc-1 == right_proc)
3261 const unsigned left_halo_id =
3262 root_left_halo_element[new_right_proc-1][irs];
3263 const unsigned left_haloed_id =
3264 root_left_haloed_element[new_right_proc-1][irs];
3266 if (right_halo_id == left_haloed_id &&
3267 right_haloed_id == left_halo_id)
3271 right_connected_segment_plus_one[right_proc][right_seg]=
3274 proc_seg_connectivity.push_back(candidate_seg);
3275 added_segment_to_the_right =
true;
3281 if (right_proc_of_new_right_proc != 0 &&
3282 right_proc_of_new_right_proc-1 == right_proc)
3288 const unsigned inv_right_halo_id =
3289 root_right_halo_element[new_right_proc-1][irs];
3290 const unsigned inv_right_haloed_id =
3291 root_right_haloed_element[new_right_proc-1][irs];
3292 if (right_halo_id == inv_right_haloed_id &&
3293 right_haloed_id == inv_right_halo_id)
3297 right_connected_segment_plus_one[right_proc][right_seg]=
3300 proc_seg_connectivity.push_back(candidate_seg);
3303 const unsigned tmp_proc =
3304 root_left_processor_plus_one[new_right_proc-1][irs];
3305 const unsigned tmp_halo =
3306 root_left_halo_element[new_right_proc-1][irs];
3307 const unsigned tmp_haloed =
3308 root_left_haloed_element[new_right_proc-1][irs];
3310 root_left_processor_plus_one[new_right_proc-1][irs] =
3311 root_right_processor_plus_one[new_right_proc-1][irs];
3312 root_left_halo_element[new_right_proc-1][irs] =
3313 root_right_halo_element[new_right_proc-1][irs];
3314 root_left_haloed_element[new_right_proc-1][irs] =
3315 root_right_haloed_element[new_right_proc-1][irs];
3317 root_right_processor_plus_one[new_right_proc-1][irs] =
3319 root_right_halo_element[new_right_proc-1][irs]=tmp_halo;
3320 root_right_haloed_element[new_right_proc-1][irs] =
3325 root_segment_inverted[new_right_proc-1][irs] = 1;
3327 added_segment_to_the_right =
true;
3335 if (!added_segment_to_the_right)
3337 std::ostringstream error_message;
3339 <<
"The corresponding processor and segment to the right of "
3340 <<
"the current right\nmost segment was not found\n";
3341 throw OomphLibError(error_message.str(),
3342 "TriangleMesh::compute_boundary_segments_connectivity_and_initial_zeta_values()",
3343 OOMPH_EXCEPTION_LOCATION);
3350 added_segment_to_the_right =
false;
3353 }
while(added_segment_to_the_left || added_segment_to_the_right);
3361 const unsigned ntotal_segments = proc_seg_connectivity.size();
3363 unsigned tmp_total_segments = 0;
3364 for (
unsigned ip =0; ip < nproc; ip++)
3366 tmp_total_segments+= root_nsegments_per_processor[ip];
3371 if (ntotal_segments!=tmp_total_segments)
3373 std::ostringstream error_message;
3375 <<
"The number of sorted segments (" << ntotal_segments <<
") on "
3376 <<
"boundary ("<< b <<
")\nis different from the total number of "
3377 <<
"segments ("<< tmp_total_segments <<
") in all\nprocessors.\n\n";
3378 throw OomphLibError(error_message.str(),
3379 OOMPH_CURRENT_FUNCTION,
3380 OOMPH_EXCEPTION_LOCATION);
3389 for (
unsigned ip = 0; ip < nproc; ip++)
3391 const unsigned nsegs_iproc = root_nsegments_per_processor[ip];
3392 root_initial_segment_arclength[ip].resize(nsegs_iproc);
3393 root_nvertices_before_segment[ip].resize(nsegs_iproc);
3396 Vector<double> aux_initial_segment_arclength(ntotal_segments);
3397 Vector<unsigned> aux_nvertices_before_segment(ntotal_segments);
3400 for (std::list<std::pair<unsigned, unsigned> >::iterator
3401 it_list = proc_seg_connectivity.begin();
3402 it_list != proc_seg_connectivity.end(); it_list++)
3404 const unsigned iproc =
static_cast<unsigned>((*it_list).first);
3405 const unsigned iseg =
static_cast<unsigned>((*it_list).second);
3406 const double iseg_arclength = root_segment_arclength[iproc][iseg];
3407 const unsigned iseg_nvertices = root_nvertices_per_segment[iproc][iseg];
3409 aux_initial_segment_arclength[ucounter] = root_accumulated_arclength;
3410 aux_nvertices_before_segment[ucounter] =
3411 root_accumulated_vertices_before_segment;
3414 root_initial_segment_arclength[iproc][iseg] = root_accumulated_arclength;
3416 root_nvertices_before_segment[iproc][iseg] =
3417 root_accumulated_vertices_before_segment;
3420 root_accumulated_arclength+= iseg_arclength;
3422 root_accumulated_vertices_before_segment+= iseg_nvertices - 1;
3431 root_accumulated_vertices_before_segment++;
3434 proc_with_initial_seg = proc_seg_connectivity.front().first;
3435 proc_with_final_seg = proc_seg_connectivity.back().first;
3438 initial_segment = proc_seg_connectivity.front().second;
3439 final_segment = proc_seg_connectivity.back().second;
3444 unsigned root_ntotal_segments = 0;
3445 for (
unsigned ip =0; ip < nproc; ip++)
3447 root_ntotal_segments+= root_nsegments_per_processor[ip];
3454 const unsigned rspu = 2;
3455 flat_packed_unsigned_send_data.clear();
3456 flat_packed_unsigned_send_data.resize(root_ntotal_segments*rspu);
3457 unsigned ucounter = 0;
3459 for (
unsigned ip = 0; ip < nproc; ip++)
3461 const unsigned nsegs_iproc = root_nsegments_per_processor[ip];
3462 for (
unsigned is = 0;
is < nsegs_iproc;
is++)
3464 flat_packed_unsigned_send_data[ucounter++] =
3465 root_nvertices_before_segment[ip][
is];
3466 flat_packed_unsigned_send_data[ucounter++] =
3467 root_segment_inverted[ip][
is];
3472 Vector<int> root_nudata_to_send(nproc,0);
3473 for (
unsigned ip =0; ip < nproc; ip++)
3476 root_nudata_to_send[ip] = root_nsegments_per_processor[ip] * rspu;
3480 Vector<int> root_uoffsets_send(nproc,0);
3481 root_uoffsets_send[0] = 0;
3482 for (
unsigned ip = 1; ip < nproc; ip++)
3485 root_uoffsets_send[ip] =
3486 root_uoffsets_send[ip-1] + root_nudata_to_send[ip-1];
3490 unsigned nutotal_data_receive = nsegments * rspu;
3492 if (my_rank!=root_processor)
3495 if (flat_packed_unsigned_send_data.size()==0)
3497 flat_packed_unsigned_send_data.resize(1);
3502 flat_packed_unsigned_receive_data.clear();
3503 flat_packed_unsigned_receive_data.resize(nutotal_data_receive);
3505 if (flat_packed_unsigned_receive_data.size()==0)
3507 flat_packed_unsigned_receive_data.resize(1);
3510 MPI_Scatterv(&flat_packed_unsigned_send_data[0],
3511 &root_nudata_to_send[0],
3512 &root_uoffsets_send[0],
3514 &flat_packed_unsigned_receive_data[0],
3515 nutotal_data_receive,
3518 comm_pt->mpi_comm());
3523 const unsigned rspd = 1;
3524 flat_packed_double_send_data.clear();
3525 flat_packed_double_send_data.resize(root_ntotal_segments*rspd);
3526 unsigned dcounter = 0;
3528 for (
unsigned ip = 0; ip < nproc; ip++)
3530 const unsigned nsegs_iproc = root_nsegments_per_processor[ip];
3531 for (
unsigned is = 0;
is < nsegs_iproc;
is++)
3533 flat_packed_double_send_data[dcounter++] =
3534 root_initial_segment_arclength[ip][
is];
3539 Vector<int> root_nddata_to_send(nproc,0);
3540 for (
unsigned ip =0; ip < nproc; ip++)
3543 root_nddata_to_send[ip] = root_nsegments_per_processor[ip] * rspd;
3547 Vector<int> root_doffsets_send(nproc,0);
3548 root_doffsets_send[0] = 0;
3549 for (
unsigned ip = 1; ip < nproc; ip++)
3552 root_doffsets_send[ip] =
3553 root_doffsets_send[ip-1] + root_nddata_to_send[ip-1];
3557 unsigned ndtotal_data_receive = nsegments * rspd;
3559 if (my_rank!=root_processor)
3562 if (flat_packed_double_send_data.size()==0)
3564 flat_packed_double_send_data.resize(1);
3569 flat_packed_double_receive_data.clear();
3570 flat_packed_double_receive_data.resize(ndtotal_data_receive);
3572 if (flat_packed_double_receive_data.size()==0)
3574 flat_packed_double_receive_data.resize(1);
3577 MPI_Scatterv(&flat_packed_double_send_data[0],
3578 &root_nddata_to_send[0],
3579 &root_doffsets_send[0],
3581 &flat_packed_double_receive_data[0],
3582 ndtotal_data_receive,
3585 comm_pt->mpi_comm());
3594 for (
unsigned is = 0;
is < nsegments;
is++)
3597 nvertices_before_segment[
is] =
3598 flat_packed_unsigned_receive_data[ucounter++];
3600 segment_inverted[
is] = flat_packed_unsigned_receive_data[ucounter++];
3602 initial_segment_arclength[
is] =
3603 flat_packed_double_receive_data[dcounter++];
3609 const unsigned numore_info = 5;
3610 Vector<unsigned> flat_package_unsigned_more_info(numore_info);
3612 flat_package_unsigned_more_info[0] = root_accumulated_vertices_before_segment;
3613 flat_package_unsigned_more_info[1] = proc_with_initial_seg;
3614 flat_package_unsigned_more_info[2] = proc_with_final_seg;
3615 flat_package_unsigned_more_info[3] = initial_segment;
3616 flat_package_unsigned_more_info[4] = final_segment;
3619 MPI_Bcast(&flat_package_unsigned_more_info[0], numore_info,
3620 MPI_UNSIGNED, root_processor, comm_pt->mpi_comm());
3623 root_accumulated_vertices_before_segment = flat_package_unsigned_more_info[0];
3624 proc_with_initial_seg = flat_package_unsigned_more_info[1];
3625 proc_with_final_seg = flat_package_unsigned_more_info[2];
3626 initial_segment = flat_package_unsigned_more_info[3];
3627 final_segment = flat_package_unsigned_more_info[4];
3630 MPI_Bcast(&root_accumulated_arclength, 1, MPI_DOUBLE,
3631 root_processor, comm_pt->mpi_comm());
3640 Boundary_initial_coordinate[b].clear();
3641 Boundary_final_coordinate[b].clear();
3643 Boundary_initial_zeta_coordinate[b].clear();
3644 Boundary_final_zeta_coordinate[b].clear();
3647 Boundary_segment_inverted[b].clear();
3648 Boundary_segment_initial_coordinate[b].clear();
3649 Boundary_segment_final_coordinate[b].clear();
3651 Boundary_segment_initial_zeta[b].clear();
3652 Boundary_segment_final_zeta[b].clear();
3654 Boundary_segment_initial_arclength[b].clear();
3655 Boundary_segment_final_arclength[b].clear();
3659 for (
unsigned is = 0;
is < nsegments;
is++)
3663 Vector<double> first_seg_coord(2);
3664 Vector<double> last_seg_coord(2);
3671 FiniteElement* first_seg_ele_pt =
3672 segment_sorted_nonhalo_ele_pt[
is].front();
3677 if (first_seg_ele_pt->is_halo())
3679 std::ostringstream error_message;
3681 <<
"The first face element in the (" <<
is <<
")-th segment is halo\n";
3682 throw OomphLibError(error_message.str(),
3683 "TriangleMesh::compute_boundary_segments_connectivity_and_initial_zeta_values()",
3684 OOMPH_EXCEPTION_LOCATION);
3689 const unsigned nnod = first_seg_ele_pt->nnode();
3692 Node *first_seg_node_pt = first_seg_ele_pt->node_pt(0);
3693 if (is_inverted[first_seg_ele_pt])
3695 first_seg_node_pt = first_seg_ele_pt->node_pt(nnod-1);
3699 FiniteElement* last_seg_ele_pt =
3700 segment_sorted_nonhalo_ele_pt[
is].back();
3705 if (last_seg_ele_pt->is_halo())
3707 std::ostringstream error_message;
3709 <<
"The last face element in the (" <<
is <<
")-th segment is halo\n";
3710 throw OomphLibError(error_message.str(),
3711 "TriangleMesh::compute_boundary_segments_connectivity_and_initial_zeta_values()",
3712 OOMPH_EXCEPTION_LOCATION);
3717 Node *last_seg_node_pt = last_seg_ele_pt->node_pt(nnod-1);
3718 if (is_inverted[last_seg_ele_pt])
3720 last_seg_node_pt = last_seg_ele_pt->node_pt(0);
3724 for (
unsigned i = 0; i < 2; i++)
3726 first_seg_coord[i] = first_seg_node_pt->x(i);
3727 last_seg_coord[i] = last_seg_node_pt->x(i);
3732 Boundary_segment_inverted[b].push_back(segment_inverted[
is]);
3736 if (!segment_inverted[
is])
3740 Boundary_segment_initial_coordinate[b].push_back(first_seg_coord);
3741 Boundary_segment_final_coordinate[b].push_back(last_seg_coord);
3748 Boundary_segment_initial_coordinate[b].push_back(last_seg_coord);
3749 Boundary_segment_final_coordinate[b].push_back(first_seg_coord);
3756 if (boundary_geom_object_pt(b)!=0)
3761 if (segment_inverted[
is])
3763 Boundary_segment_initial_zeta[b].push_back(final_zeta_segment[
is]);
3764 Boundary_segment_final_zeta[b].push_back(initial_zeta_segment[
is]);
3768 Boundary_segment_initial_zeta[b].push_back(initial_zeta_segment[
is]);
3769 Boundary_segment_final_zeta[b].push_back(final_zeta_segment[
is]);
3776 Boundary_segment_initial_arclength[b].push_back(
3777 initial_segment_arclength[
is]);
3779 Boundary_segment_final_arclength[b].push_back(
3780 initial_segment_arclength[
is] + segment_arclength[
is]);
3788 if (segment_all_nodes_pt.size() != nsegments)
3790 std::ostringstream error_message;
3792 <<
"The number of segments ("<<nsegments<<
") and the number of "
3793 <<
"set of nodes ("<<segment_all_nodes_pt.size()<<
") representing\n"
3794 <<
"the\nsegments is different!!!\n\n";
3795 throw OomphLibError(error_message.str(),
3796 "TriangleMesh::compute_boundary_segments_connectivity_and_initial_zeta_values()",
3797 OOMPH_EXCEPTION_LOCATION);
3811 Vector<double> first_coordinate(2);
3812 Vector<double> last_coordinate(2);
3816 Vector<double> first_node_zeta_coordinate(1,0.0);
3817 Vector<double> last_node_zeta_coordinate(1,0.0);
3821 const unsigned ndtotal_data = 3;
3822 Vector<double> flat_packed_double_data_initial_seg(ndtotal_data);
3826 if (my_rank == proc_with_initial_seg)
3829 FiniteElement* first_ele_pt = 0;
3831 Node *first_node_pt = 0;
3833 if (!segment_inverted[initial_segment])
3837 first_ele_pt = segment_sorted_ele_pt[initial_segment].front();
3840 const unsigned nnod = first_ele_pt->nnode();
3843 first_node_pt = first_ele_pt->node_pt(0);
3844 if (is_inverted[first_ele_pt])
3846 first_node_pt = first_ele_pt->node_pt(nnod-1);
3853 first_ele_pt = segment_sorted_ele_pt[initial_segment].back();
3856 const unsigned nnod = first_ele_pt->nnode();
3859 first_node_pt = first_ele_pt->node_pt(nnod-1);
3860 if (is_inverted[first_ele_pt])
3862 first_node_pt = first_ele_pt->node_pt(0);
3867 for (
unsigned i = 0; i < 2; i++)
3869 flat_packed_double_data_initial_seg[i] = first_node_pt->x(i);
3873 Vector<double> tmp_zeta(1);
3874 first_node_pt->get_coordinates_on_boundary(b, tmp_zeta);
3878 if (this->boundary_geom_object_pt(b)!=0)
3886 if (tmp_zeta[0] >= 1.0e-14)
3893 flat_packed_double_data_initial_seg[2] = tmp_zeta[0];
3899 MPI_Bcast(&flat_packed_double_data_initial_seg[0], ndtotal_data,
3900 MPI_DOUBLE, proc_with_initial_seg, comm_pt->mpi_comm());
3904 for (
unsigned i = 0; i < 2; i++)
3906 first_coordinate[i] = flat_packed_double_data_initial_seg[i];
3908 first_node_zeta_coordinate[0]=flat_packed_double_data_initial_seg[2];
3913 Vector<double> flat_packed_double_data_final_seg(ndtotal_data);
3917 if (my_rank == proc_with_final_seg)
3920 FiniteElement* last_ele_pt = 0;
3923 Node *last_node_pt = 0;
3926 if (!segment_inverted[final_segment])
3930 last_ele_pt = segment_sorted_ele_pt[final_segment].back();
3933 const unsigned nnod = last_ele_pt->nnode();
3936 last_node_pt = last_ele_pt->node_pt(nnod-1);
3937 if (is_inverted[last_ele_pt])
3939 last_node_pt = last_ele_pt->node_pt(0);
3946 last_ele_pt = segment_sorted_ele_pt[final_segment].front();
3949 const unsigned nnod = last_ele_pt->nnode();
3952 last_node_pt = last_ele_pt->node_pt(0);
3953 if (is_inverted[last_ele_pt])
3955 last_node_pt = last_ele_pt->node_pt(nnod-1);
3960 for (
unsigned i = 0; i < 2; i++)
3962 flat_packed_double_data_final_seg[i]=last_node_pt->x(i);
3966 Vector<double> tmp_zeta(1);
3967 last_node_pt->get_coordinates_on_boundary(b, tmp_zeta);
3971 if (this->boundary_geom_object_pt(b)!=0)
3980 if (std::fabs(tmp_zeta[0] - root_accumulated_arclength) >= 1.0e-14)
3982 tmp_zeta[0] = root_accumulated_arclength;
3987 flat_packed_double_data_final_seg[2] = tmp_zeta[0];
3993 MPI_Bcast(&flat_packed_double_data_final_seg[0], ndtotal_data,
3994 MPI_DOUBLE, proc_with_final_seg, comm_pt->mpi_comm());
3998 for (
unsigned i = 0; i < 2; i++)
4000 last_coordinate[i] = flat_packed_double_data_final_seg[i];
4002 last_node_zeta_coordinate[0]=flat_packed_double_data_final_seg[2];
4006 Boundary_initial_coordinate[b] = first_coordinate;
4007 Boundary_final_coordinate[b] = last_coordinate;
4009 Boundary_initial_zeta_coordinate[b] = first_node_zeta_coordinate;
4010 Boundary_final_zeta_coordinate[b] = last_node_zeta_coordinate;
4014 if (is_internal_boundary)
4025 re_assign_initial_zeta_values_for_internal_boundary(
4026 b, segment_sorted_nonhalo_ele_pt, is_inverted);
4037 identify_boundary_segments_and_assign_initial_zeta_values(b,
this);
4041 for (
unsigned i = 0; i < n_all_face_ele; i++)
4043 delete all_face_ele_pt[i];
4044 all_face_ele_pt[i] = 0;
4057 template<
class ELEMENT>
4061 Vector<std::list<FiniteElement*> > &old_segment_sorted_ele_pt,
4062 std::map<FiniteElement*, bool> &old_is_inverted)
4069 Vector<FiniteElement*> face_el_pt;
4077 unsigned n_repeated_ele = 0;
4079 const unsigned n_regions = this->nregion();
4082 Vector<std::pair<Node*, Node*> > done_nodes_pt;
4088 for (
unsigned rr = 0 ; rr < n_regions; rr++)
4090 const unsigned region_id =
4091 static_cast<unsigned>(this->Region_attribute[rr]);
4094 const unsigned nel_in_region =
4095 this->nboundary_element_in_region(b, region_id);
4097 unsigned nel_repetead_in_region = 0;
4101 if (nel_in_region > 0)
4103 bool repeated =
false;
4106 for (
unsigned e = 0; e < nel_in_region; e++)
4110 FiniteElement* bulk_elem_pt =
4111 this->boundary_element_in_region_pt(b, region_id, e);
4114 if (bulk_elem_pt->is_halo())
4122 this->face_index_at_boundary_in_region(b,region_id,e);
4127 FiniteElement* tmp_ele_pt =
4128 new DummyFaceElement<ELEMENT>(bulk_elem_pt, face_index);
4130 const unsigned n_nodes = tmp_ele_pt->nnode();
4132 std::pair<Node*, Node*> tmp_pair =
4133 std::make_pair(tmp_ele_pt->node_pt(0),
4134 tmp_ele_pt->node_pt(n_nodes - 1));
4136 std::pair<Node*, Node*> tmp_pair_inverse =
4137 std::make_pair(tmp_ele_pt->node_pt(n_nodes - 1),
4138 tmp_ele_pt->node_pt(0));
4141 const unsigned repeated_nodes_size = done_nodes_pt.size();
4142 for (
unsigned l = 0; l < repeated_nodes_size; l++)
4144 if (tmp_pair == done_nodes_pt[l] ||
4145 tmp_pair_inverse == done_nodes_pt[l])
4147 nel_repetead_in_region++;
4157 done_nodes_pt.push_back(tmp_pair);
4159 face_el_pt.push_back(tmp_ele_pt);
4173 nele += nel_in_region;
4175 n_repeated_ele += nel_repetead_in_region;
4184 nele = this->nboundary_element(b);
4190 bool repeated =
false;
4193 for (
unsigned e = 0; e < nele; e++)
4197 FiniteElement* bulk_elem_pt = this->boundary_element_pt(b, e);
4200 if (bulk_elem_pt->is_halo())
4207 int face_index = this->face_index_at_boundary(b, e);
4212 FiniteElement* tmp_ele_pt =
4213 new DummyFaceElement<ELEMENT>(bulk_elem_pt, face_index);
4215 const unsigned n_nodes = tmp_ele_pt->nnode();
4217 std::pair<Node*, Node*> tmp_pair =
4218 std::make_pair(tmp_ele_pt->node_pt(0),
4219 tmp_ele_pt->node_pt(n_nodes - 1));
4221 std::pair<Node*, Node*> tmp_pair_inverse =
4222 std::make_pair(tmp_ele_pt->node_pt(n_nodes - 1),
4223 tmp_ele_pt->node_pt(0));
4226 const unsigned repeated_nodes_size = done_nodes_pt.size();
4227 for (
unsigned l = 0; l < repeated_nodes_size; l++)
4229 if (tmp_pair == done_nodes_pt[l] ||
4230 tmp_pair_inverse == done_nodes_pt[l])
4244 done_nodes_pt.push_back(tmp_pair);
4246 face_el_pt.push_back(tmp_ele_pt);
4264 nele-= n_repeated_ele;
4267 if (nele!=face_el_pt.size())
4269 std::ostringstream error_message;
4271 <<
"The independet counting of face elements ("<<nele<<
") for "
4272 <<
"boundary ("<<b<<
") is different\n"
4273 <<
"from the real number of face elements in the container ("
4274 << face_el_pt.size() <<
")\n";
4276 throw OomphLibError(error_message.str(),
4277 OOMPH_CURRENT_FUNCTION,
4278 OOMPH_EXCEPTION_LOCATION);
4287 const unsigned nnon_halo_face_elements = face_el_pt.size();
4291 Vector<std::list<FiniteElement*> > segment_sorted_ele_pt;
4294 unsigned nsorted_face_elements = 0;
4297 std::map<FiniteElement*, bool> done_el;
4300 std::map<FiniteElement*, bool> is_inverted;
4303 while(nsorted_face_elements < nnon_halo_face_elements)
4307 std::list<FiniteElement*> sorted_el_pt;
4311 bool found_initial_face_element =
false;
4314 FiniteElement* ele_face_pt = 0;
4317 for (iface = 0; iface < nele; iface++)
4319 ele_face_pt = face_el_pt[iface];
4321 if (!done_el[ele_face_pt])
4325 found_initial_face_element =
true;
4328 nsorted_face_elements++;
4333 sorted_el_pt.push_back(ele_face_pt);
4335 done_el[ele_face_pt] =
true;
4341 if (!found_initial_face_element)
4343 std::ostringstream error_message;
4345 <<
"Could not find an initial face element for the current segment\n";
4346 throw OomphLibError(error_message.str(),
4347 "TriangleMesh::re_assign_initial_zeta_values_for_internal_boundary()",
4348 OOMPH_EXCEPTION_LOCATION);
4353 const unsigned nnod = ele_face_pt->nnode();
4357 Node* left_node_pt = ele_face_pt->node_pt(0);
4358 Node* right_node_pt = ele_face_pt->node_pt(nnod - 1);
4362 bool face_element_added =
false;
4371 for (
unsigned iiface = iface; iiface < nele; iiface++)
4374 face_element_added =
false;
4377 ele_face_pt = face_el_pt[iiface];
4381 if (!(done_el[ele_face_pt]))
4384 Node* local_left_node_pt = ele_face_pt->node_pt(0);
4385 Node* local_right_node_pt = ele_face_pt->node_pt(nnod - 1);
4388 if (left_node_pt == local_right_node_pt)
4390 left_node_pt = local_left_node_pt;
4391 sorted_el_pt.push_front(ele_face_pt);
4392 is_inverted[ele_face_pt] =
false;
4393 face_element_added =
true;
4396 else if (left_node_pt == local_left_node_pt)
4398 left_node_pt = local_right_node_pt;
4399 sorted_el_pt.push_front(ele_face_pt);
4400 is_inverted[ele_face_pt] =
true;
4401 face_element_added =
true;
4404 else if (right_node_pt == local_left_node_pt)
4406 right_node_pt = local_right_node_pt;
4407 sorted_el_pt.push_back(ele_face_pt);
4408 is_inverted[ele_face_pt] =
false;
4409 face_element_added =
true;
4412 else if (right_node_pt == local_right_node_pt)
4414 right_node_pt = local_left_node_pt;
4415 sorted_el_pt.push_back(ele_face_pt);
4416 is_inverted[ele_face_pt] =
true;
4417 face_element_added =
true;
4420 if (face_element_added)
4422 done_el[ele_face_pt] =
true;
4423 nsorted_face_elements++;
4431 }
while(face_element_added &&
4432 (nsorted_face_elements < nnon_halo_face_elements));
4435 segment_sorted_ele_pt.push_back(sorted_el_pt);
4446 const unsigned nsegments = segment_sorted_ele_pt.size();
4449 if (nnon_halo_face_elements > 0 && nsegments == 0)
4451 std::ostringstream error_message;
4453 <<
"The number of segments is zero, but the number of nonhalo\n"
4454 <<
"elements is: (" << nnon_halo_face_elements <<
")\n";
4455 throw OomphLibError(error_message.str(),
4456 OOMPH_CURRENT_FUNCTION,
4457 OOMPH_EXCEPTION_LOCATION);
4464 Vector<std::set<Node*> > segment_all_nodes_pt(nsegments);
4468 Vector<Vector<Node*> > sorted_segment_all_nodes_pt(nsegments);
4473 Vector<Vector<double> > sorted_segment_node_arclength(nsegments);
4476 Vector<double> segment_arclength(nsegments);
4479 Vector<unsigned> nvertices_per_segment(nsegments);
4482 Vector<double> initial_zeta_segment(nsegments);
4485 Vector<double> final_zeta_segment(nsegments);
4489 for (
unsigned is = 0;
is < nsegments;
is++)
4492 if (segment_sorted_ele_pt[
is].size() == 0)
4494 std::ostringstream error_message;
4496 <<
"The (" <<
is <<
")-th segment has no elements\n";
4497 throw OomphLibError(error_message.str(),
4498 "TriangleMesh::re_assign_initial_zeta_values_for_internal_boundary()",
4499 OOMPH_EXCEPTION_LOCATION);
4504 FiniteElement* first_ele_pt = segment_sorted_ele_pt[
is].front();
4507 const unsigned nnod = first_ele_pt->nnode();
4510 Node *first_node_pt = first_ele_pt->node_pt(0);
4511 if (is_inverted[first_ele_pt])
4513 first_node_pt = first_ele_pt->node_pt(nnod-1);
4517 double x_left = first_node_pt->x(0);
4518 double y_left = first_node_pt->x(1);
4522 Vector<double> zeta(1, 0.0);
4527 if (this->boundary_geom_object_pt(b)!=0)
4529 first_node_pt->get_coordinates_on_boundary(b, zeta);
4530 initial_zeta_segment[
is] = zeta[0];
4533 FiniteElement* last_ele_pt = segment_sorted_ele_pt[
is].back();
4536 Node *last_node_pt = last_ele_pt->node_pt(nnod-1);
4537 if (is_inverted[last_ele_pt])
4539 last_node_pt = last_ele_pt->node_pt(0);
4542 last_node_pt->get_coordinates_on_boundary(b, zeta);
4543 final_zeta_segment[
is] = zeta[0];
4548 std::set<Node*> local_nodes_pt;
4549 local_nodes_pt.insert(first_node_pt);
4552 Vector<double> sorted_node_arclength;
4553 sorted_node_arclength.push_back(0.0);
4557 Vector<Node*> sorted_nodes_pt;
4558 sorted_nodes_pt.push_back(first_node_pt);
4561 for (std::list<FiniteElement*>::iterator it =
4562 segment_sorted_ele_pt[
is].begin();
4563 it != segment_sorted_ele_pt[
is].end(); it++)
4566 FiniteElement* el_pt = *it;
4571 if (is_inverted[el_pt])
4578 for (
unsigned j = 1; j < nnod; j++)
4580 Node* nod_pt = el_pt->node_pt(k_nod);
4584 double x_right = nod_pt->x(0);
4585 double y_right = nod_pt->x(1);
4589 (x_right - x_left) * (x_right - x_left) + (y_right - y_left)
4590 * (y_right - y_left));
4595 if (this->boundary_geom_object_pt(b)==0)
4607 local_nodes_pt.insert(nod_pt);
4610 sorted_node_arclength.push_back(zeta[0]);
4613 sorted_nodes_pt.push_back(nod_pt);
4622 segment_arclength[
is] = zeta[0];
4627 nvertices_per_segment[
is] = local_nodes_pt.size();
4630 segment_all_nodes_pt[
is] = local_nodes_pt;
4633 sorted_segment_node_arclength[
is] = sorted_node_arclength;
4636 sorted_segment_all_nodes_pt[
is] = sorted_nodes_pt;
4651 const unsigned old_nsegments = old_segment_sorted_ele_pt.size();
4655 Vector<unsigned> old_boundary_segment_inverted(old_nsegments);
4657 Vector<Vector<double> >
4658 old_boundary_segment_initial_coordinate(old_nsegments);
4659 Vector<Vector<double> >
4660 old_boundary_segment_final_coordinate(old_nsegments);
4662 Vector<double> old_boundary_segment_initial_zeta(old_nsegments);
4663 Vector<double> old_boundary_segment_final_zeta(old_nsegments);
4665 Vector<double> old_boundary_segment_initial_arclength(old_nsegments);
4666 Vector<double> old_boundary_segment_final_arclength(old_nsegments);
4669 for (
unsigned old_is = 0; old_is < old_nsegments; old_is++)
4671 old_boundary_segment_inverted[old_is] =
4672 boundary_segment_inverted(b)[old_is];
4674 old_boundary_segment_initial_coordinate[old_is].resize(2);
4675 old_boundary_segment_final_coordinate[old_is].resize(2);
4676 for (
unsigned i = 0; i < 2; i++)
4678 old_boundary_segment_initial_coordinate[old_is][i] =
4679 boundary_segment_initial_coordinate(b)[old_is][i];
4681 old_boundary_segment_final_coordinate[old_is][i] =
4682 boundary_segment_final_coordinate(b)[old_is][i];
4686 if (this->boundary_geom_object_pt(b)!=0)
4688 old_boundary_segment_initial_zeta[old_is] =
4689 boundary_segment_initial_zeta(b)[old_is];
4691 old_boundary_segment_final_zeta[old_is] =
4692 boundary_segment_final_zeta(b)[old_is];
4697 old_boundary_segment_initial_arclength[old_is] =
4698 boundary_segment_initial_arclength(b)[old_is];
4700 old_boundary_segment_final_arclength[old_is] =
4701 boundary_segment_final_arclength(b)[old_is];
4709 Boundary_segment_inverted[b].clear();
4710 Boundary_segment_initial_coordinate[b].clear();
4711 Boundary_segment_final_coordinate[b].clear();
4713 Boundary_segment_initial_zeta[b].clear();
4714 Boundary_segment_final_zeta[b].clear();
4716 Boundary_segment_initial_arclength[b].clear();
4717 Boundary_segment_final_arclength[b].clear();
4720 Boundary_segment_inverted[b].resize(nsegments);
4721 Boundary_segment_initial_coordinate[b].resize(nsegments);
4722 Boundary_segment_final_coordinate[b].resize(nsegments);
4725 if (this->boundary_geom_object_pt(b)!=0)
4727 Boundary_segment_initial_zeta[b].resize(nsegments);
4728 Boundary_segment_final_zeta[b].resize(nsegments);
4732 Boundary_segment_initial_arclength[b].resize(nsegments);
4733 Boundary_segment_final_arclength[b].resize(nsegments);
4737 std::map<unsigned, bool> done_segment;
4740 unsigned re_assigned_segments = 0;
4743 for (
unsigned old_is = 0; old_is < old_nsegments; old_is++)
4746 const double old_initial_arclength =
4747 old_boundary_segment_initial_arclength[old_is];
4748 const double old_final_arclength =
4749 old_boundary_segment_final_arclength[old_is];
4751 const unsigned old_inverted_segment =
4752 old_boundary_segment_inverted[old_is];
4756 bool old_increasing_order =
false;
4757 if (old_initial_arclength < old_final_arclength)
4758 {old_increasing_order =
true;}
4762 FiniteElement* first_old_seg_ele_pt =
4763 old_segment_sorted_ele_pt[old_is].front();
4766 const unsigned nnod = first_old_seg_ele_pt->nnode();
4769 Node *first_old_seg_node_pt = first_old_seg_ele_pt->node_pt(0);
4770 if (old_is_inverted[first_old_seg_ele_pt])
4772 first_old_seg_node_pt = first_old_seg_ele_pt->node_pt(nnod-1);
4776 FiniteElement* last_old_seg_ele_pt =
4777 old_segment_sorted_ele_pt[old_is].back();
4780 Node *last_old_seg_node_pt = last_old_seg_ele_pt->node_pt(nnod-1);
4781 if (old_is_inverted[last_old_seg_ele_pt])
4783 last_old_seg_node_pt = last_old_seg_ele_pt->node_pt(0);
4787 if (old_inverted_segment)
4789 Node* temp_node_pt = first_old_seg_node_pt;
4790 first_old_seg_node_pt = last_old_seg_node_pt;
4791 last_old_seg_node_pt = temp_node_pt;
4797 for (
unsigned is = 0;
is < nsegments;
is++)
4799 if (!done_segment[
is])
4803 bool found_first_old_seg_node =
false;
4804 bool found_last_old_seg_node =
false;
4805 bool same_order =
false;
4808 FiniteElement* first_seg_ele_pt = segment_sorted_ele_pt[
is].front();
4809 Node* first_seg_node_pt = first_seg_ele_pt->node_pt(0);
4810 if (is_inverted[first_seg_ele_pt])
4811 {first_seg_node_pt = first_seg_ele_pt->node_pt(nnod-1);}
4814 const double segment_first_node_zeta =
4815 sorted_segment_node_arclength[
is][0];
4818 Vector<double> first_node_coord(2);
4819 for (
unsigned i = 0; i < 2; i++)
4820 {first_node_coord[i] = first_seg_node_pt->x(i);}
4823 FiniteElement* last_seg_ele_pt = segment_sorted_ele_pt[
is].back();
4824 Node* last_seg_node_pt = last_seg_ele_pt->node_pt(nnod-1);
4825 if (is_inverted[last_seg_ele_pt])
4826 {last_seg_node_pt = last_seg_ele_pt->node_pt(0);}
4829 const double segment_final_node_zeta = segment_arclength[
is];
4832 Vector<double> last_node_coord(2);
4833 for (
unsigned i = 0; i < 2; i++)
4834 {last_node_coord[i] = last_seg_node_pt->x(i);}
4837 Vector<Node*> segment_node_pt = sorted_segment_all_nodes_pt[
is];
4839 const unsigned nsegment_node = segment_node_pt.size();
4840 for (
unsigned in = 0; in < nsegment_node; in++)
4842 Node* current_node_pt = segment_node_pt[in];
4843 if (!found_first_old_seg_node &&
4844 first_old_seg_node_pt == current_node_pt)
4848 const double current_node_zeta =
4849 sorted_segment_node_arclength[
is][in];
4853 if (!found_last_old_seg_node)
4856 Boundary_segment_initial_coordinate[b][
is] = first_node_coord;
4859 if (this->boundary_geom_object_pt(b)!=0)
4866 Boundary_segment_initial_zeta[b][
is] =
4867 initial_zeta_segment[
is];
4873 const double distance =
4874 std::fabs(current_node_zeta - segment_first_node_zeta);
4876 double new_initial_arclength = old_initial_arclength;
4879 if (old_increasing_order)
4882 new_initial_arclength-= distance;
4887 new_initial_arclength+= distance;
4891 Boundary_segment_initial_arclength[b][
is] =
4892 new_initial_arclength;
4899 Boundary_segment_initial_coordinate[b][
is] = last_node_coord;
4902 if (this->boundary_geom_object_pt(b)!=0)
4910 Boundary_segment_initial_zeta[b][
is] =
4911 final_zeta_segment[
is];
4917 const double distance =
4918 std::fabs(current_node_zeta - segment_final_node_zeta);
4920 double new_initial_arclength = old_initial_arclength;
4923 if (old_increasing_order)
4926 new_initial_arclength-= distance;
4931 new_initial_arclength+= distance;
4935 Boundary_segment_initial_arclength[b][
is] =
4936 new_initial_arclength;
4942 found_first_old_seg_node =
true;
4950 if (found_first_old_seg_node && !found_last_old_seg_node)
4951 {same_order =
true;}
4953 if (!found_last_old_seg_node &&
4954 last_old_seg_node_pt == current_node_pt)
4958 const double current_node_zeta =
4959 sorted_segment_node_arclength[
is][in];
4963 if (found_first_old_seg_node)
4966 Boundary_segment_final_coordinate[b][
is] = last_node_coord;
4969 if (this->boundary_geom_object_pt(b)!=0)
4976 Boundary_segment_final_zeta[b][
is] =
4977 final_zeta_segment[
is];
4983 const double distance =
4984 std::fabs(current_node_zeta - segment_final_node_zeta);
4986 double new_final_arclength = old_final_arclength;
4989 if (old_increasing_order)
4992 new_final_arclength+= distance;
4997 new_final_arclength-= distance;
5001 Boundary_segment_final_arclength[b][
is] = new_final_arclength;
5008 Boundary_segment_final_coordinate[b][
is] = first_node_coord;
5011 if (this->boundary_geom_object_pt(b)!=0)
5019 Boundary_segment_final_zeta[b][
is] =
5020 initial_zeta_segment[
is];
5026 const double distance =
5027 std::fabs(current_node_zeta - segment_first_node_zeta);
5029 double new_final_arclength = old_final_arclength;
5032 if (old_increasing_order)
5035 new_final_arclength+= distance;
5040 new_final_arclength-= distance;
5044 Boundary_segment_final_arclength[b][
is] = new_final_arclength;
5050 found_last_old_seg_node =
true;
5057 if (!found_first_old_seg_node && found_last_old_seg_node)
5058 {same_order =
false;}
5060 if (found_first_old_seg_node && found_last_old_seg_node)
5065 {Boundary_segment_inverted[b][
is] = old_inverted_segment;}
5067 {Boundary_segment_inverted[b][
is] = !old_inverted_segment;}
5070 done_segment[
is] =
true;
5073 re_assigned_segments++;
5082 if ((found_first_old_seg_node && !found_last_old_seg_node) ||
5083 (!found_first_old_seg_node && found_last_old_seg_node))
5085 std::stringstream error_message;
5087 <<
"Working with boundary ("<< b <<
").\nOnly the first node or "
5088 <<
"the last node of the old segment (" << old_is <<
") was\n"
5089 <<
"found. Both, first and last node should have been found in "
5090 <<
"the same segment!!!.\n"
5091 <<
"Found first seg node:" << found_first_old_seg_node <<
"\n"
5092 <<
"Found last seg node:" << found_last_old_seg_node <<
"\n\n";
5093 throw OomphLibError(error_message.str(),
5094 "TriangleMesh::re_assign_initial_zeta_values_for_internal_boundary()",
5095 OOMPH_EXCEPTION_LOCATION);
5108 for (
unsigned is = 0;
is < nsegments;
is++)
5111 if (!done_segment[
is])
5114 FiniteElement* first_seg_ele_pt =
5115 segment_sorted_ele_pt[
is].front();
5117 const unsigned nnod = first_seg_ele_pt->nnode();
5119 Node* first_seg_node_pt = first_seg_ele_pt->node_pt(0);
5120 if (is_inverted[first_seg_ele_pt])
5121 {first_seg_node_pt = first_seg_ele_pt->node_pt(nnod-1);}
5124 const double segment_first_node_zeta =
5125 sorted_segment_node_arclength[
is][0];
5128 Vector<double> first_node_coord(2);
5129 for (
unsigned i = 0; i < 2; i++)
5130 {first_node_coord[i] = first_seg_node_pt->x(i);}
5133 FiniteElement* last_seg_ele_pt =
5134 segment_sorted_ele_pt[
is].back();
5135 Node* last_seg_node_pt = last_seg_ele_pt->node_pt(nnod-1);
5136 if (is_inverted[last_seg_ele_pt])
5137 {last_seg_node_pt = last_seg_ele_pt->node_pt(0);}
5140 const double segment_final_node_zeta = segment_arclength[
is];
5143 Vector<double> last_node_coord(2);
5144 for (
unsigned i = 0; i < 2; i++)
5145 {last_node_coord[i] = last_seg_node_pt->x(i);}
5148 Boundary_segment_initial_coordinate[b][
is] = first_node_coord;
5151 if (this->boundary_geom_object_pt(b)!=0)
5158 Boundary_segment_initial_zeta[b][
is] =
5159 initial_zeta_segment[
is];
5165 Boundary_segment_initial_arclength[b][
is] =
5166 segment_first_node_zeta;
5171 Boundary_segment_final_coordinate[b][
is] = last_node_coord;
5174 if (this->boundary_geom_object_pt(b)!=0)
5181 Boundary_segment_final_zeta[b][
is] =
5182 final_zeta_segment[
is];
5188 Boundary_segment_final_arclength[b][
is] =
5189 segment_final_node_zeta;
5193 Boundary_segment_inverted[b][
is] = 0;
5196 done_segment[
is] =
true;
5199 re_assigned_segments++;
5207 if (re_assigned_segments != nsegments)
5209 std::stringstream error_message;
5211 <<
"Working with boundary ("<< b <<
").\nThe number of re-assigned "
5212 <<
"segments (" << re_assigned_segments
5213 <<
") is different from the number\nof segments ("<< nsegments
5215 throw OomphLibError(error_message.str(),
5216 "TriangleMesh::re_assign_initial_zeta_values_for_internal_boundary()",
5217 OOMPH_EXCEPTION_LOCATION);
5222 for (
unsigned i = 0; i < nele; i++)
5224 delete face_el_pt[i];
5239 template <
class ELEMENT>
5243 bool &is_internal_boundary,
5244 std::map<FiniteElement*,FiniteElement*>
5245 &face_to_bulk_element_pt)
5248 OomphCommunicator* comm_pt = this->communicator_pt();
5250 const unsigned my_rank = comm_pt->my_rank();
5258 Vector<FiniteElement*> tmp_face_ele_pt;
5260 const unsigned nregions = this->nregion();
5266 for (
unsigned ir = 0 ; ir < nregions; ir++)
5268 const unsigned region_id =
5269 static_cast<unsigned>(this->Region_attribute[ir]);
5272 const unsigned nele_in_region =
5273 this->nboundary_element_in_region(b, region_id);
5277 if (nele_in_region > 0)
5280 for (
unsigned e = 0; e < nele_in_region; e++)
5284 FiniteElement* bulk_ele_pt =
5285 this->boundary_element_in_region_pt(b, region_id, e);
5290 this->face_index_at_boundary_in_region(b,region_id,e);
5293 FiniteElement* tmp_face_el_pt =
5294 new DummyFaceElement<ELEMENT>(bulk_ele_pt, face_index);
5297 face_to_bulk_element_pt[tmp_face_el_pt] = bulk_ele_pt;
5302 tmp_face_ele_pt.push_back(tmp_face_el_pt);
5316 const unsigned nbound_ele = this->nboundary_element(b);
5322 for (
unsigned e = 0; e < nbound_ele; e++)
5326 FiniteElement* bulk_ele_pt = this->boundary_element_pt(b, e);
5330 int face_index = this->face_index_at_boundary(b, e);
5333 FiniteElement* tmp_face_el_pt =
5334 new DummyFaceElement<ELEMENT>(bulk_ele_pt, face_index);
5337 face_to_bulk_element_pt[tmp_face_el_pt] = bulk_ele_pt;
5342 tmp_face_ele_pt.push_back(tmp_face_el_pt);
5351 std::map<FiniteElement*,bool> done_face;
5355 is_internal_boundary =
false;
5359 Vector<FiniteElement*> free_memory_face_ele_pt;
5363 const unsigned n_tmp_face_ele = tmp_face_ele_pt.size();
5364 for (
unsigned ie = 0; ie < n_tmp_face_ele; ie++)
5367 FiniteElement* main_face_ele_pt = tmp_face_ele_pt[ie];
5368 if (!done_face[main_face_ele_pt])
5371 done_face[main_face_ele_pt] =
true;
5373 const unsigned nnodes = main_face_ele_pt->nnode();
5375 Node* main_first_node_pt = main_face_ele_pt->node_pt(0);
5376 Node* main_last_node_pt = main_face_ele_pt->node_pt(nnodes-1);
5380 for (
unsigned iie = ie + 1; iie < n_tmp_face_ele; iie++)
5383 FiniteElement* dependant_face_ele_pt = tmp_face_ele_pt[iie];
5384 if (!done_face[dependant_face_ele_pt])
5388 Node* dependant_first_node_pt =
5389 dependant_face_ele_pt->node_pt(0);
5390 Node* dependant_last_node_pt =
5391 dependant_face_ele_pt->node_pt(nnodes-1);
5394 if (((dependant_first_node_pt == main_first_node_pt) &&
5395 (dependant_last_node_pt == main_last_node_pt)) ||
5396 ((dependant_first_node_pt == main_last_node_pt) &&
5397 (dependant_last_node_pt == main_first_node_pt)))
5401 is_internal_boundary =
true;
5403 done_face[dependant_face_ele_pt] =
true;
5414 FiniteElement *main_bulk_ele_pt =
5415 face_to_bulk_element_pt[main_face_ele_pt];
5416 FiniteElement *dependant_bulk_ele_pt =
5417 face_to_bulk_element_pt[dependant_face_ele_pt];
5421 int processor_in_charge_main_bulk_ele =
5422 main_bulk_ele_pt->non_halo_proc_ID();
5423 int processor_in_charge_dependant_bulk_ele =
5424 dependant_bulk_ele_pt->non_halo_proc_ID();
5429 if (processor_in_charge_main_bulk_ele < 0)
5431 processor_in_charge_main_bulk_ele=
5432 static_cast<int>(my_rank);
5434 if (processor_in_charge_dependant_bulk_ele < 0)
5436 processor_in_charge_dependant_bulk_ele=
5437 static_cast<int>(my_rank);
5442 bool add_main_face_element =
true;
5443 if (processor_in_charge_dependant_bulk_ele >
5444 processor_in_charge_main_bulk_ele)
5447 add_main_face_element =
false;
5449 else if (processor_in_charge_main_bulk_ele ==
5450 processor_in_charge_dependant_bulk_ele)
5456 Vector<double> main_ele_coordinates(2);
5457 Vector<double> dependant_ele_coordinates(2);
5460 const unsigned n_bulk_nodes =
5461 main_bulk_ele_pt->nnode();
5462 for (
unsigned inode = 0; inode < n_bulk_nodes;
5465 for (
unsigned idim = 0; idim < 2; idim++)
5467 main_ele_coordinates[idim]+=
5468 main_bulk_ele_pt->node_pt(inode)->
5470 dependant_ele_coordinates[idim]+=
5471 dependant_bulk_ele_pt->node_pt(inode)->
5478 for (
unsigned idim = 0; idim < 2; idim++)
5480 main_ele_coordinates[idim]/=
5481 (double)n_bulk_nodes;
5482 dependant_ele_coordinates[idim]/=
5483 (double)n_bulk_nodes;
5489 if (dependant_ele_coordinates[1] <
5490 main_ele_coordinates[1])
5491 {add_main_face_element =
false;}
5492 else if(dependant_ele_coordinates[1]==
5493 main_ele_coordinates[1])
5496 if(dependant_ele_coordinates[0] <
5497 main_ele_coordinates[0])
5498 {add_main_face_element =
false;}
5503 if (add_main_face_element)
5508 face_ele_pt.push_back(main_face_ele_pt);
5511 free_memory_face_ele_pt.
5512 push_back(dependant_face_ele_pt);
5519 face_ele_pt.push_back(dependant_face_ele_pt);
5522 free_memory_face_ele_pt.
5523 push_back(main_face_ele_pt);
5542 const unsigned n_free_face_ele = free_memory_face_ele_pt.size();
5543 if (n_free_face_ele == 0)
5551 face_ele_pt.resize(n_tmp_face_ele);
5553 for (
unsigned i = 0; i < n_tmp_face_ele; i++)
5555 face_ele_pt[i] = tmp_face_ele_pt[i];
5563 for (
unsigned i = 0; i < n_free_face_ele; i++)
5565 delete free_memory_face_ele_pt[i];
5566 free_memory_face_ele_pt[i] = 0;
5578 template <
class ELEMENT>
5587 OomphCommunicator* comm_pt = this->communicator_pt();
5589 const unsigned nproc = comm_pt->nproc();
5590 const unsigned my_rank = comm_pt->my_rank();
5594 Vector<FiniteElement*> tmp_face_ele_pt;
5596 const unsigned nregions = this->nregion();
5600 std::map<FiniteElement*,FiniteElement*> face_to_bulk_element_pt;
5606 for (
unsigned ir = 0 ; ir < nregions; ir++)
5608 const unsigned region_id =
5609 static_cast<unsigned>(this->Region_attribute[ir]);
5612 const unsigned nele_in_region =
5613 this->nboundary_element_in_region(b, region_id);
5617 if (nele_in_region > 0)
5620 for (
unsigned e = 0; e < nele_in_region; e++)
5623 FiniteElement* bulk_ele_pt =
5624 this->boundary_element_in_region_pt(b, region_id, e);
5627 int face_index=this->face_index_at_boundary_in_region(b,region_id,e);
5630 FiniteElement* tmp_face_el_pt =
5631 new DummyFaceElement<ELEMENT>(bulk_ele_pt, face_index);
5636 tmp_face_ele_pt.push_back(tmp_face_el_pt);
5638 face_to_bulk_element_pt[tmp_face_el_pt] = bulk_ele_pt;
5652 const unsigned nbound_ele = this->nboundary_element(b);
5658 for (
unsigned e = 0; e < nbound_ele; e++)
5661 FiniteElement* bulk_ele_pt = this->boundary_element_pt(b, e);
5664 int face_index = this->face_index_at_boundary(b, e);
5667 FiniteElement* tmp_face_el_pt =
5668 new DummyFaceElement<ELEMENT>(bulk_ele_pt, face_index);
5672 tmp_face_ele_pt.push_back(tmp_face_el_pt);
5674 face_to_bulk_element_pt[tmp_face_el_pt] = bulk_ele_pt;
5685 Vector<FiniteElement*> face_ele_pt;
5688 std::map<FiniteElement*,bool> done_face;
5691 bool is_internal_boundary =
false;
5695 bool is_internal_boundary_paranoid =
false;
5699 unsigned nfound_face_elements = 0;
5703 const unsigned nbound_ele = tmp_face_ele_pt.size();
5704 for (
unsigned ie = 0; ie < nbound_ele; ie++)
5707 FiniteElement* main_face_ele_pt = tmp_face_ele_pt[ie];
5708 if (!done_face[main_face_ele_pt])
5711 done_face[main_face_ele_pt] =
true;
5713 const unsigned nnodes = main_face_ele_pt->nnode();
5715 Node* main_first_node_pt = main_face_ele_pt->node_pt(0);
5716 Node* main_last_node_pt = main_face_ele_pt->node_pt(nnodes-1);
5718 for (
unsigned iie = ie + 1; iie < nbound_ele; iie++)
5721 FiniteElement* dependant_face_ele_pt = tmp_face_ele_pt[iie];
5722 if (!done_face[dependant_face_ele_pt])
5725 Node* dependant_first_node_pt =
5726 dependant_face_ele_pt->node_pt(0);
5727 Node* dependant_last_node_pt =
5728 dependant_face_ele_pt->node_pt(nnodes-1);
5731 if (((dependant_first_node_pt == main_first_node_pt) &&
5732 (dependant_last_node_pt == main_last_node_pt)) ||
5733 ((dependant_first_node_pt == main_last_node_pt) &&
5734 (dependant_last_node_pt == main_first_node_pt)))
5738 nfound_face_elements+=2;
5742 is_internal_boundary =
true;
5744 done_face[dependant_face_ele_pt] =
true;
5753 FiniteElement *main_bulk_ele_pt =
5754 face_to_bulk_element_pt[main_face_ele_pt];
5755 FiniteElement *dependant_bulk_ele_pt =
5756 face_to_bulk_element_pt[dependant_face_ele_pt];
5759 int processor_in_charge_main_bulk_ele =
5760 main_bulk_ele_pt->non_halo_proc_ID();
5761 int processor_in_charge_dependant_bulk_ele =
5762 dependant_bulk_ele_pt->non_halo_proc_ID();
5767 if (processor_in_charge_main_bulk_ele < 0)
5769 processor_in_charge_main_bulk_ele=
static_cast<int>(my_rank);
5771 if (processor_in_charge_dependant_bulk_ele < 0)
5773 processor_in_charge_dependant_bulk_ele=
static_cast<int>(my_rank);
5777 bool add_main_face_element =
true;
5778 if (processor_in_charge_dependant_bulk_ele >
5779 processor_in_charge_main_bulk_ele)
5782 add_main_face_element =
false;
5784 else if (processor_in_charge_main_bulk_ele ==
5785 processor_in_charge_dependant_bulk_ele)
5790 Vector<double> main_ele_coordinates(2);
5791 Vector<double> dependant_ele_coordinates(2);
5793 const unsigned n_bulk_nodes = main_bulk_ele_pt->nnode();
5794 for (
unsigned inode = 0; inode < n_bulk_nodes; inode++)
5796 for (
unsigned idim = 0; idim < 2; idim++)
5798 main_ele_coordinates[idim]+=
5799 main_bulk_ele_pt->node_pt(inode)->x(idim);
5800 dependant_ele_coordinates[idim]+=
5801 dependant_bulk_ele_pt->node_pt(inode)->x(idim);
5806 for (
unsigned idim = 0; idim < 2; idim++)
5808 main_ele_coordinates[idim]/=(double)n_bulk_nodes;
5809 dependant_ele_coordinates[idim]/=(double)n_bulk_nodes;
5815 if (dependant_ele_coordinates[1] < main_ele_coordinates[1])
5816 {add_main_face_element =
false;}
5817 else if(dependant_ele_coordinates[1]==main_ele_coordinates[1])
5820 if(dependant_ele_coordinates[0] < main_ele_coordinates[0])
5821 {add_main_face_element =
false;}
5826 if (add_main_face_element)
5830 face_ele_pt.push_back(main_face_ele_pt);
5836 face_ele_pt.push_back(dependant_face_ele_pt);
5849 const unsigned nface_ele = face_ele_pt.size();
5855 if (nbound_ele > 0 && nfound_face_elements == nbound_ele)
5856 {is_internal_boundary_paranoid =
true;}
5858 if (nbound_ele > 0 && is_internal_boundary_paranoid &&
5859 nbound_ele!=nface_ele*2)
5861 std::ostringstream error_message;
5863 <<
"The info. to perform the synchronisation of the boundary "
5864 <<
"coordinates was not completely established\n"
5865 <<
"In this case it was the number of non repeated boundary elements\n"
5866 <<
"Number of boundary elements: (" << nbound_ele <<
")\n"
5867 <<
"Number of nonrepeated boundary elements: (" << nface_ele <<
")\n";
5868 throw OomphLibError(error_message.str(),
5869 "TriangleMesh::synchronize_boundary_coordinates()",
5870 OOMPH_EXCEPTION_LOCATION);
5880 std::vector<bool> is_halo_face_element(nface_ele,
false);
5883 unsigned nnon_halo_face_elements = 0;
5885 for (
unsigned ie = 0; ie < nface_ele; ie++)
5887 FiniteElement* face_el_pt = face_ele_pt[ie];
5889 FiniteElement* tmp_bulk_ele_pt = face_to_bulk_element_pt[face_el_pt];
5891 if (!tmp_bulk_ele_pt->is_halo())
5893 is_halo_face_element[ie] =
false;
5894 nnon_halo_face_elements++;
5899 is_halo_face_element[ie] =
true;
5912 std::map<Node*,bool> done_node;
5916 Vector<Vector<Node*> > face_halo_node_pt(nproc);
5920 Vector<Vector<unsigned> > face_halo_node_id(nproc);
5924 Vector<Vector<Node*> > face_haloed_node_pt(nproc);
5928 Vector<Vector<unsigned> > face_haloed_node_id(nproc);
5932 std::map<Node*,bool> done_haloed_face_node;
5935 for (
unsigned iface = 0; iface < nface_ele; iface++)
5938 if (!is_halo_face_element[iface])
5941 FiniteElement *ele_face_pt = face_ele_pt[iface];
5943 const unsigned nnodes = ele_face_pt->nnode();
5945 for (
unsigned in = 0; in < nnodes; in++)
5947 Node* face_node_pt = ele_face_pt->node_pt(in);
5949 if (!done_node[face_node_pt])
5952 done_node[face_node_pt] =
true;
5954 if (face_node_pt->is_halo())
5957 int int_nonhalo_ID = face_node_pt->non_halo_proc_ID();
5959 if (int_nonhalo_ID < 0)
5961 std::ostringstream error_message;
5963 <<
"The node was marked to be halo but the processor in "
5964 <<
"charge was found to be -1\n\n";
5965 throw OomphLibError(error_message.str(),
5966 "TriangleMesh::synchronize_boundary_coordinates()",
5967 OOMPH_EXCEPTION_LOCATION);
5970 const unsigned ip =
static_cast<unsigned>(int_nonhalo_ID);
5974 face_halo_node_pt[ip].push_back(face_node_pt);
5978 bool found_halo_node =
false;
5980 const unsigned nhalo_iproc = this->nhalo_node(ip);
5981 for (
unsigned ihn = 0; ihn < nhalo_iproc; ihn++)
5983 Node* compare_face_node_pt = this->halo_node_pt(ip, ihn);
5984 if (compare_face_node_pt == face_node_pt)
5988 face_halo_node_id[ip].push_back(ihn);
5991 found_halo_node =
true;
5998 if (!found_halo_node)
6000 std::ostringstream error_message;
6002 <<
"The halo id of the current node: ("
6003 << face_node_pt->x(0) <<
", " << face_node_pt->x(1)
6004 <<
") with processor (" << ip <<
") was not found!!!\n\n";
6005 throw OomphLibError(error_message.str(),
6006 "TriangleMesh::synchronize_boundary_coordinates()",
6007 OOMPH_EXCEPTION_LOCATION);
6017 for (
unsigned ip = 0; ip < nproc; ip++)
6029 const unsigned nhaloed_iproc = this->nhaloed_node(ip);
6030 for (
unsigned ihdn = 0; ihdn < nhaloed_iproc; ihdn++)
6032 Node* compare_face_node_pt=this->haloed_node_pt(ip, ihdn);
6033 if (face_node_pt == compare_face_node_pt)
6037 face_haloed_node_pt[ip].push_back(face_node_pt);
6040 face_haloed_node_id[ip].push_back(ihdn);
6044 done_haloed_face_node[face_node_pt] =
true;
6070 for (
unsigned ip = 0; ip < nproc; ip++)
6075 const unsigned nhalo_face_nodes = face_halo_node_pt[ip].size();
6077 if (nhalo_face_nodes!=face_halo_node_id[ip].size())
6079 std::ostringstream error_message;
6081 <<
"The number of found halo face nodes (" << nhalo_face_nodes
6082 <<
") is different from the number of\nfound halo face ids ("
6083 << face_halo_node_id[ip].size() <<
")!!!\n\n";
6084 throw OomphLibError(error_message.str(),
6085 "TriangleMesh::synchronize_boundary_coordinates()",
6086 OOMPH_EXCEPTION_LOCATION);
6092 Vector<unsigned> flat_unsigned_send_packed_data;
6093 Vector<double> flat_double_send_packed_data;
6096 for (
unsigned ihfn = 0; ihfn < nhalo_face_nodes; ihfn++)
6099 Node *halo_face_node_pt = face_halo_node_pt[ip][ihfn];
6101 const unsigned halo_id = face_halo_node_id[ip][ihfn];
6103 Vector<double> zeta(1);
6104 halo_face_node_pt->get_coordinates_on_boundary(b, zeta);
6106 flat_unsigned_send_packed_data.push_back(halo_id);
6107 flat_double_send_packed_data.push_back(zeta[0]);
6112 MPI_Request request;
6115 int send_proc =
static_cast<int>(ip);
6117 int receive_proc =
static_cast<int>(ip);
6120 Vector<unsigned> flat_unsigned_receive_packed_data;
6121 Vector<double> flat_double_receive_packed_data;
6125 unsigned nflat_unsigned_send = flat_unsigned_send_packed_data.size();
6126 MPI_Isend(&nflat_unsigned_send,1,MPI_UNSIGNED,
6127 send_proc,1,comm_pt->mpi_comm(),&request);
6129 unsigned nflat_unsigned_receive = 0;
6130 MPI_Recv(&nflat_unsigned_receive,1,MPI_UNSIGNED,
6131 receive_proc,1,comm_pt->mpi_comm(),&status);
6133 MPI_Wait(&request,MPI_STATUS_IGNORE);
6135 if (nflat_unsigned_send!=0)
6137 MPI_Isend(&flat_unsigned_send_packed_data[0],nflat_unsigned_send,
6138 MPI_UNSIGNED,send_proc,2,comm_pt->mpi_comm(),&request);
6141 if (nflat_unsigned_receive!=0)
6143 flat_unsigned_receive_packed_data.resize(nflat_unsigned_receive);
6144 MPI_Recv(&flat_unsigned_receive_packed_data[0],nflat_unsigned_receive,
6145 MPI_UNSIGNED,receive_proc,2,comm_pt->mpi_comm(),&status);
6148 if (nflat_unsigned_send!=0)
6150 MPI_Wait(&request,MPI_STATUS_IGNORE);
6155 unsigned nflat_double_send = flat_double_send_packed_data.size();
6156 MPI_Isend(&nflat_double_send,1,MPI_DOUBLE,
6157 send_proc,3,comm_pt->mpi_comm(),&request);
6159 unsigned nflat_double_receive = 0;
6160 MPI_Recv(&nflat_double_receive,1,MPI_DOUBLE,
6161 receive_proc,3,comm_pt->mpi_comm(),&status);
6163 MPI_Wait(&request,MPI_STATUS_IGNORE);
6165 if (nflat_double_send!=0)
6167 MPI_Isend(&flat_double_send_packed_data[0],nflat_double_send,
6168 MPI_DOUBLE,send_proc,4,comm_pt->mpi_comm(),&request);
6171 if (nflat_double_receive!=0)
6173 flat_double_receive_packed_data.resize(nflat_double_receive);
6174 MPI_Recv(&flat_double_receive_packed_data[0],nflat_double_receive,
6175 MPI_DOUBLE,receive_proc,4,comm_pt->mpi_comm(),&status);
6178 if (nflat_double_send!=0)
6180 MPI_Wait(&request,MPI_STATUS_IGNORE);
6185 if (nflat_unsigned_receive!=nflat_double_receive)
6187 std::ostringstream error_message;
6189 <<
"The number of unsigned received data ("
6190 << nflat_unsigned_receive <<
") is different from the "
6191 <<
"number\nof double received data ("
6192 << nflat_double_receive <<
")!!!\n\n";
6193 throw OomphLibError(error_message.str(),
6194 "TriangleMesh::synchronize_boundary_coordinates()",
6195 OOMPH_EXCEPTION_LOCATION);
6202 for (
unsigned iflat_packed = 0; iflat_packed < nflat_unsigned_receive;
6206 const unsigned haloed_id =
6207 flat_unsigned_receive_packed_data[iflat_packed];
6209 Vector<double> zeta(1);
6210 zeta[0] = flat_double_receive_packed_data[iflat_packed];
6213 Node* haloed_face_node_pt = this->haloed_node_pt(ip, haloed_id);
6227 if (!done_haloed_face_node[haloed_face_node_pt])
6230 haloed_face_node_pt->set_coordinates_on_boundary(b, zeta);
6233 for (
unsigned iiproc = 0; iiproc < nproc; iiproc++)
6236 if (iiproc != my_rank)
6239 const unsigned nhaloed_node_iiproc = this->nhaloed_node(iiproc);
6240 for (
unsigned ihdn = 0; ihdn < nhaloed_node_iiproc; ihdn++)
6242 Node* compare_haloed_node_pt=this->haloed_node_pt(iiproc,ihdn);
6243 if (haloed_face_node_pt == compare_haloed_node_pt)
6247 face_haloed_node_pt[iiproc].push_back(haloed_face_node_pt);
6250 face_haloed_node_id[iiproc].push_back(ihdn);
6271 for (
unsigned ip = 0; ip < nproc; ip++)
6278 Vector<unsigned> flat_unsigned_send_packed_data;
6279 Vector<double> flat_double_send_packed_data;
6283 const unsigned nhaloed_face_nodes = face_haloed_node_pt[ip].size();
6285 for (
unsigned ihdfn = 0; ihdfn < nhaloed_face_nodes; ihdfn++)
6288 Node *haloed_face_node_pt = face_haloed_node_pt[ip][ihdfn];
6290 const unsigned haloed_id = face_haloed_node_id[ip][ihdfn];
6292 Vector<double> zeta(1);
6293 haloed_face_node_pt->get_coordinates_on_boundary(b, zeta);
6295 flat_unsigned_send_packed_data.push_back(haloed_id);
6296 flat_double_send_packed_data.push_back(zeta[0]);
6301 MPI_Request request;
6304 int send_proc =
static_cast<int>(ip);
6306 int receive_proc =
static_cast<int>(ip);
6309 Vector<unsigned> flat_unsigned_receive_packed_data;
6310 Vector<double> flat_double_receive_packed_data;
6314 unsigned nflat_unsigned_send = flat_unsigned_send_packed_data.size();
6315 MPI_Isend(&nflat_unsigned_send,1,MPI_UNSIGNED,
6316 send_proc,1,comm_pt->mpi_comm(),&request);
6318 unsigned nflat_unsigned_receive = 0;
6319 MPI_Recv(&nflat_unsigned_receive,1,MPI_UNSIGNED,
6320 receive_proc,1,comm_pt->mpi_comm(),&status);
6322 MPI_Wait(&request,MPI_STATUS_IGNORE);
6324 if (nflat_unsigned_send!=0)
6326 MPI_Isend(&flat_unsigned_send_packed_data[0],nflat_unsigned_send,
6327 MPI_UNSIGNED,send_proc,2,comm_pt->mpi_comm(),&request);
6330 if (nflat_unsigned_receive!=0)
6332 flat_unsigned_receive_packed_data.resize(nflat_unsigned_receive);
6333 MPI_Recv(&flat_unsigned_receive_packed_data[0],nflat_unsigned_receive,
6334 MPI_UNSIGNED,receive_proc,2,comm_pt->mpi_comm(),&status);
6337 if (nflat_unsigned_send!=0)
6339 MPI_Wait(&request,MPI_STATUS_IGNORE);
6344 unsigned nflat_double_send = flat_double_send_packed_data.size();
6345 MPI_Isend(&nflat_double_send,1,MPI_DOUBLE,
6346 send_proc,3,comm_pt->mpi_comm(),&request);
6348 unsigned nflat_double_receive = 0;
6349 MPI_Recv(&nflat_double_receive,1,MPI_DOUBLE,
6350 receive_proc,3,comm_pt->mpi_comm(),&status);
6352 MPI_Wait(&request,MPI_STATUS_IGNORE);
6354 if (nflat_double_send!=0)
6356 MPI_Isend(&flat_double_send_packed_data[0],nflat_double_send,
6357 MPI_DOUBLE,send_proc,4,comm_pt->mpi_comm(),&request);
6360 if (nflat_double_receive!=0)
6362 flat_double_receive_packed_data.resize(nflat_double_receive);
6363 MPI_Recv(&flat_double_receive_packed_data[0],nflat_double_receive,
6364 MPI_DOUBLE,receive_proc,4,comm_pt->mpi_comm(),&status);
6367 if (nflat_double_send!=0)
6369 MPI_Wait(&request,MPI_STATUS_IGNORE);
6374 if (nflat_unsigned_receive!=nflat_double_receive)
6376 std::ostringstream error_message;
6378 <<
"The number of unsigned received data ("
6379 << nflat_unsigned_receive <<
") is different from the "
6380 <<
"number\nof double received data ("
6381 << nflat_double_receive <<
")!!!\n\n";
6382 throw OomphLibError(error_message.str(),
6383 "TriangleMesh::synchronize_boundary_coordinates()",
6384 OOMPH_EXCEPTION_LOCATION);
6391 for (
unsigned iflat_packed = 0; iflat_packed < nflat_unsigned_receive;
6395 const unsigned halo_id =
6396 flat_unsigned_receive_packed_data[iflat_packed];
6398 Vector<double> zeta(1);
6399 zeta[0] = flat_double_receive_packed_data[iflat_packed];
6402 Node* halo_face_node_pt = this->halo_node_pt(ip, halo_id);
6413 halo_face_node_pt->set_coordinates_on_boundary(b, zeta);
6419 for (
unsigned ie = 0; ie < nbound_ele; ie++)
6421 delete tmp_face_ele_pt[ie];
6422 tmp_face_ele_pt[ie] = 0;
6427 if (is_internal_boundary)
6429 re_scale_re_assigned_initial_zeta_values_for_internal_boundary(b);
6440 template<
class ELEMENT>
6450 Vector<FiniteElement*> face_el_pt;
6458 unsigned n_repeated_ele = 0;
6460 const unsigned n_regions = this->nregion();
6463 Vector<std::pair<Node*, Node*> > done_nodes_pt;
6469 for (
unsigned rr = 0 ; rr < n_regions; rr++)
6471 const unsigned region_id =
6472 static_cast<unsigned>(this->Region_attribute[rr]);
6475 const unsigned nel_in_region =
6476 this->nboundary_element_in_region(b, region_id);
6478 unsigned nel_repetead_in_region = 0;
6482 if (nel_in_region > 0)
6484 bool repeated =
false;
6487 for (
unsigned e = 0; e < nel_in_region; e++)
6491 FiniteElement* bulk_elem_pt =
6492 this->boundary_element_in_region_pt(b, region_id, e);
6495 if (bulk_elem_pt->is_halo())
6503 this->face_index_at_boundary_in_region(b,region_id,e);
6508 FiniteElement* tmp_ele_pt =
6509 new DummyFaceElement<ELEMENT>(bulk_elem_pt, face_index);
6511 const unsigned n_nodes = tmp_ele_pt->nnode();
6513 std::pair<Node*, Node*> tmp_pair =
6514 std::make_pair(tmp_ele_pt->node_pt(0),
6515 tmp_ele_pt->node_pt(n_nodes - 1));
6517 std::pair<Node*, Node*> tmp_pair_inverse =
6518 std::make_pair(tmp_ele_pt->node_pt(n_nodes - 1),
6519 tmp_ele_pt->node_pt(0));
6522 const unsigned n_done_nodes = done_nodes_pt.size();
6523 for (
unsigned l = 0; l < n_done_nodes; l++)
6525 if (tmp_pair == done_nodes_pt[l] ||
6526 tmp_pair_inverse == done_nodes_pt[l])
6528 nel_repetead_in_region++;
6538 done_nodes_pt.push_back(tmp_pair);
6540 face_el_pt.push_back(tmp_ele_pt);
6554 nele += nel_in_region;
6556 n_repeated_ele += nel_repetead_in_region;
6565 nele = this->nboundary_element(b);
6571 bool repeated =
false;
6574 for (
unsigned e = 0; e < nele; e++)
6578 FiniteElement* bulk_elem_pt = this->boundary_element_pt(b, e);
6581 if (bulk_elem_pt->is_halo())
6589 int face_index = this->face_index_at_boundary(b, e);
6594 FiniteElement* tmp_ele_pt =
6595 new DummyFaceElement<ELEMENT>(bulk_elem_pt, face_index);
6597 const unsigned n_nodes = tmp_ele_pt->nnode();
6599 std::pair<Node*, Node*> tmp_pair =
6600 std::make_pair(tmp_ele_pt->node_pt(0),
6601 tmp_ele_pt->node_pt(n_nodes - 1));
6603 std::pair<Node*, Node*> tmp_pair_inverse =
6604 std::make_pair(tmp_ele_pt->node_pt(n_nodes - 1),
6605 tmp_ele_pt->node_pt(0));
6608 const unsigned n_done_nodes = done_nodes_pt.size();
6609 for (
unsigned l = 0; l < n_done_nodes; l++)
6611 if (tmp_pair == done_nodes_pt[l] ||
6612 tmp_pair_inverse == done_nodes_pt[l])
6626 done_nodes_pt.push_back(tmp_pair);
6628 face_el_pt.push_back(tmp_ele_pt);
6646 nele-= n_repeated_ele;
6649 if (nele!=face_el_pt.size())
6651 std::ostringstream error_message;
6653 <<
"The independet counting of face elements ("<<nele<<
") for "
6654 <<
"boundary ("<<b<<
") is different\n"
6655 <<
"from the real number of face elements in the container ("
6656 << face_el_pt.size() <<
")\n";
6658 throw OomphLibError(error_message.str(),
6659 "TriangleMesh::re_scale_re_assigned_initial_zeta_values_for_internal_boundary()",
6660 OOMPH_EXCEPTION_LOCATION);
6670 const unsigned nnon_halo_face_elements = face_el_pt.size();
6674 Vector<std::list<FiniteElement*> > segment_sorted_ele_pt;
6677 unsigned nsorted_face_elements = 0;
6680 std::map<FiniteElement*, bool> done_el;
6683 std::map<FiniteElement*, bool> is_inverted;
6686 while(nsorted_face_elements < nnon_halo_face_elements)
6690 std::list<FiniteElement*> sorted_el_pt;
6694 bool found_initial_face_element =
false;
6697 FiniteElement* ele_face_pt = 0;
6700 for (iface = 0; iface < nele; iface++)
6702 ele_face_pt = face_el_pt[iface];
6704 if (!done_el[ele_face_pt])
6707 found_initial_face_element =
true;
6709 nsorted_face_elements++;
6711 sorted_el_pt.push_back(ele_face_pt);
6713 done_el[ele_face_pt] =
true;
6719 if (!found_initial_face_element)
6721 std::ostringstream error_message;
6723 <<
"Could not find an initial face element for the current segment\n";
6725 throw OomphLibError(error_message.str(),
6726 "TriangleMesh::re_scale_re_assigned_initial_zeta_values_for_internal_boundary()",
6727 OOMPH_EXCEPTION_LOCATION);
6732 const unsigned nnod = ele_face_pt->nnode();
6736 Node* left_node_pt = ele_face_pt->node_pt(0);
6737 Node* right_node_pt = ele_face_pt->node_pt(nnod - 1);
6741 bool face_element_added =
false;
6750 for (
unsigned iiface = iface; iiface < nele; iiface++)
6753 face_element_added =
false;
6756 ele_face_pt = face_el_pt[iiface];
6759 if (!(done_el[ele_face_pt]))
6762 Node* local_left_node_pt = ele_face_pt->node_pt(0);
6763 Node* local_right_node_pt = ele_face_pt->node_pt(nnod - 1);
6766 if (left_node_pt == local_right_node_pt)
6768 left_node_pt = local_left_node_pt;
6769 sorted_el_pt.push_front(ele_face_pt);
6770 is_inverted[ele_face_pt] =
false;
6771 face_element_added =
true;
6774 else if (left_node_pt == local_left_node_pt)
6776 left_node_pt = local_right_node_pt;
6777 sorted_el_pt.push_front(ele_face_pt);
6778 is_inverted[ele_face_pt] =
true;
6779 face_element_added =
true;
6782 else if (right_node_pt == local_left_node_pt)
6784 right_node_pt = local_right_node_pt;
6785 sorted_el_pt.push_back(ele_face_pt);
6786 is_inverted[ele_face_pt] =
false;
6787 face_element_added =
true;
6790 else if (right_node_pt == local_right_node_pt)
6792 right_node_pt = local_left_node_pt;
6793 sorted_el_pt.push_back(ele_face_pt);
6794 is_inverted[ele_face_pt] =
true;
6795 face_element_added =
true;
6798 if (face_element_added)
6800 done_el[ele_face_pt] =
true;
6801 nsorted_face_elements++;
6807 }
while(face_element_added &&
6808 (nsorted_face_elements < nnon_halo_face_elements));
6811 segment_sorted_ele_pt.push_back(sorted_el_pt);
6824 Vector<std::set<Node*> > segment_all_nodes_pt;
6827 const unsigned nsegments = segment_sorted_ele_pt.size();
6830 if (nnon_halo_face_elements > 0 && nsegments == 0)
6832 std::ostringstream error_message;
6834 <<
"The number of segments is zero, but the number of nonhalo\n"
6835 <<
"elements is: (" << nnon_halo_face_elements <<
")\n";
6836 throw OomphLibError(error_message.str(),
6837 "TriangleMesh::re_scale_re_assigned_initial_zeta_values_for_internal_boundary()",
6838 OOMPH_EXCEPTION_LOCATION);
6843 Vector<double> segment_arclength(nsegments);
6846 Vector<double> initial_zeta_segment(nsegments);
6849 Vector<double> final_zeta_segment(nsegments);
6853 for (
unsigned is = 0;
is < nsegments;
is++)
6856 if (segment_sorted_ele_pt[
is].size() == 0)
6858 std::ostringstream error_message;
6860 <<
"The (" <<
is <<
")-th segment has no elements\n";
6861 throw OomphLibError(error_message.str(),
6862 "TriangleMesh::re_scale_re_assigned_initial_zeta_values_for_internal_boundary()",
6863 OOMPH_EXCEPTION_LOCATION);
6868 FiniteElement* first_ele_pt = segment_sorted_ele_pt[
is].front();
6871 const unsigned nnod = first_ele_pt->nnode();
6874 Node *first_node_pt = first_ele_pt->node_pt(0);
6875 if (is_inverted[first_ele_pt])
6877 first_node_pt = first_ele_pt->node_pt(nnod-1);
6881 FiniteElement* last_ele_pt = segment_sorted_ele_pt[
is].back();
6884 Node *last_node_pt = last_ele_pt->node_pt(nnod-1);
6885 if (is_inverted[last_ele_pt])
6887 last_node_pt = last_ele_pt->node_pt(0);
6891 double x_left = first_node_pt->x(0);
6892 double y_left = first_node_pt->x(1);
6896 Vector<double> zeta(1, 0.0);
6901 if (this->boundary_geom_object_pt(b)!=0)
6903 first_node_pt->get_coordinates_on_boundary(b, zeta);
6904 initial_zeta_segment[
is] = zeta[0];
6905 last_node_pt->get_coordinates_on_boundary(b, zeta);
6906 final_zeta_segment[
is] = zeta[0];
6910 std::set<Node*> local_nodes_pt;
6911 local_nodes_pt.insert(first_node_pt);
6914 for (std::list<FiniteElement*>::iterator it =
6915 segment_sorted_ele_pt[
is].begin();
6916 it != segment_sorted_ele_pt[
is].end(); it++)
6919 FiniteElement* el_pt = *it;
6924 if (is_inverted[el_pt])
6931 for (
unsigned j = 1; j < nnod; j++)
6933 Node* nod_pt = el_pt->node_pt(k_nod);
6937 double x_right = nod_pt->x(0);
6938 double y_right = nod_pt->x(1);
6942 (x_right - x_left) * (x_right - x_left) + (y_right - y_left)
6943 * (y_right - y_left));
6951 local_nodes_pt.insert(nod_pt);
6957 segment_arclength[
is] = zeta[0];
6960 segment_all_nodes_pt.push_back(local_nodes_pt);
6972 Boundary_segment_inverted[b].clear();
6973 Boundary_segment_initial_coordinate[b].clear();
6974 Boundary_segment_final_coordinate[b].clear();
6976 Boundary_segment_initial_zeta[b].clear();
6977 Boundary_segment_final_zeta[b].clear();
6979 Boundary_segment_initial_arclength[b].clear();
6980 Boundary_segment_final_arclength[b].clear();
6983 Vector<double> first_node_zeta_coordinate(1,0.0);
6984 Vector<double> last_node_zeta_coordinate(1,0.0);
6985 first_node_zeta_coordinate = boundary_initial_zeta_coordinate(b);
6986 last_node_zeta_coordinate = boundary_final_zeta_coordinate(b);
6989 const double boundary_arclength =
6990 std::max(first_node_zeta_coordinate[0], last_node_zeta_coordinate[0]);
6994 for (
unsigned is = 0;
is < nsegments;
is++)
6997 FiniteElement* first_face_ele_pt = segment_sorted_ele_pt[
is].front();
7000 const unsigned nnod = first_face_ele_pt->nnode();
7003 Node* first_node_pt = first_face_ele_pt->node_pt(0);
7004 if (is_inverted[first_face_ele_pt])
7006 first_node_pt = first_face_ele_pt->node_pt(nnod-1);
7010 Vector<double> zeta_first(1);
7011 first_node_pt->get_coordinates_on_boundary(b, zeta_first);
7014 FiniteElement* last_face_ele_pt = segment_sorted_ele_pt[
is].back();
7017 Node* last_node_pt = last_face_ele_pt->node_pt(nnod-1);
7018 if (is_inverted[last_face_ele_pt])
7020 last_node_pt = last_face_ele_pt->node_pt(0);
7024 Vector<double> zeta_last(1);
7025 last_node_pt->get_coordinates_on_boundary(b, zeta_last);
7029 Vector<double> first_node_coord(2);
7030 Vector<double> last_node_coord(2);
7031 for (
unsigned i = 0; i < 2; i++)
7033 first_node_coord[i] = first_node_pt->x(i);
7034 last_node_coord[i] = last_node_pt->x(i);
7038 Boundary_segment_inverted[b].push_back(0);
7039 Boundary_segment_initial_coordinate[b].push_back(first_node_coord);
7040 Boundary_segment_final_coordinate[b].push_back(last_node_coord);
7043 if (this->boundary_geom_object_pt(b)!=0)
7045 Boundary_segment_initial_zeta[b].push_back(zeta_first[0]);
7046 Boundary_segment_final_zeta[b].push_back(zeta_last[0]);
7051 Boundary_segment_initial_arclength[b].push_back(
7052 zeta_first[0] * boundary_arclength);
7053 Boundary_segment_final_arclength[b].push_back(
7054 zeta_last[0] * boundary_arclength);
7060 for (
unsigned i = 0; i < nele; i++)
7062 delete face_el_pt[i];
7068 #endif // OOMPH_HAS_MPI
7072 #ifdef OOMPH_HAS_TRIANGLE_LIB
7077 template <
class ELEMENT>
7080 TriangulateIO& triangulate_io,
7081 bool &use_attributes)
7086 std::ifstream poly_file(poly_file_name.c_str(),std::ios_base::in);
7089 throw OomphLibError(
"Error opening .poly file\n",
7090 OOMPH_CURRENT_FUNCTION,
7091 OOMPH_EXCEPTION_LOCATION);
7095 TriangleHelper::initialise_triangulateio(triangulate_io);
7098 poly_file.ignore(80,
'\n');
7101 unsigned invertices;
7102 poly_file>>invertices;
7103 triangulate_io.numberofpoints=invertices;
7106 triangulate_io.pointlist =
7107 (
double *) malloc(triangulate_io.numberofpoints * 2 *
sizeof(
double));
7111 poly_file>>mesh_dim;
7121 throw OomphLibError(
"The dimension must be 2\n",
7122 OOMPH_CURRENT_FUNCTION,
7123 OOMPH_EXCEPTION_LOCATION);
7129 poly_file>> nextras;
7131 triangulate_io.numberofpointattributes = 0;
7132 triangulate_io.pointattributelist = (
double *) NULL;
7135 unsigned nodemarkers;
7136 poly_file>>nodemarkers;
7137 triangulate_io.pointmarkerlist = (
int *) NULL;
7142 if(nextras!=0 || nodemarkers!=0)
7144 oomph_info <<
"===================================================="
7145 << std::endl<<std::endl;
7146 oomph_info <<
"Reading the .poly file via oomph_lib \n"
7147 <<
"point's attribute and point's markers \n"
7148 <<
"are automatically set to 0"<<std::endl;
7149 oomph_info <<
"===================================================="
7155 unsigned dummy_value;
7156 unsigned count_point=0;
7157 std::string test_string;
7160 getline(poly_file,test_string,
'#');
7161 poly_file.ignore(80,
'\n');
7165 for(
unsigned count=0;count<invertices;count++)
7167 poly_file>>dummy_value;
7168 poly_file>>triangulate_io.pointlist[count_point];
7169 poly_file>>triangulate_io.pointlist[count_point+1];
7170 if(nextras!=0 || nodemarkers!=0)
7172 for(
unsigned j=0;j<nextras;j++)
7174 poly_file>>dummy_value;
7177 else if(nextras!=0 && nodemarkers!=0)
7179 for(
unsigned j=0;j<nextras;j++)
7181 poly_file>>dummy_value;
7182 poly_file>>dummy_value;
7186 poly_file.ignore(80,
'\n');
7189 if(poly_file.get() ==
'#')
7191 poly_file.ignore(80,
'\n');
7207 unsigned inelements;
7208 poly_file>>inelements;
7210 unsigned segment_markers;
7211 poly_file>>segment_markers;
7216 if(segment_markers!=1)
7219 std::ostringstream error_stream;
7221 <<
"The segment marker should be provided \n"
7222 <<
"In order to assign each segment to a boundary \n "<< std::endl;
7224 throw OomphLibError(error_stream.str(),
7225 OOMPH_CURRENT_FUNCTION,
7226 OOMPH_EXCEPTION_LOCATION);
7230 triangulate_io.numberofsegments = inelements;
7231 triangulate_io.segmentlist =
7232 (
int *) malloc(triangulate_io.numberofsegments * 2 *
sizeof(
int));
7233 triangulate_io.segmentmarkerlist =
7234 (
int *) malloc(triangulate_io.numberofsegments *
sizeof(
int));
7237 for(
unsigned i=0;i<2*inelements;i+=2)
7239 poly_file>>dummy_seg;
7240 poly_file>>triangulate_io.segmentlist[i];
7241 poly_file>>triangulate_io.segmentlist[i+1];
7242 if(segment_markers!=0)
7244 poly_file>>triangulate_io.segmentmarkerlist[i/2];
7248 poly_file.ignore(80,
'\n');
7253 if(getline(poly_file,test_string,
'#'))
7255 poly_file.ignore(80,
'\n');
7257 unsigned dummy_hole;
7261 triangulate_io.numberofholes = nhole;
7262 triangulate_io.holelist =
7263 (
double *) malloc(triangulate_io.numberofholes * 2 *
sizeof(
double));
7267 for(
unsigned i=0;i<2*nhole;i+=2)
7269 poly_file>>dummy_hole;
7270 poly_file>>triangulate_io.holelist[i];
7271 poly_file>>triangulate_io.holelist[i+1];
7277 if(getline(poly_file,test_string,
'#'))
7279 poly_file.ignore(80,
'\n');
7281 unsigned dummy_region;
7284 std::cerr <<
"Regions: "<< nregion << std::endl;
7287 triangulate_io.numberofregions = nregion;
7288 triangulate_io.regionlist =
7289 (
double *) malloc(triangulate_io.numberofregions * 4 *
sizeof(
double));
7293 {use_attributes=
true;}
7297 for(
unsigned i=0;i<nregion;i++)
7299 poly_file>>dummy_region;
7300 poly_file>>triangulate_io.regionlist[4*i];
7301 poly_file>>triangulate_io.regionlist[4*i+1];
7302 poly_file>>triangulate_io.regionlist[4*i+2];
7303 triangulate_io.regionlist[4*i+3] = 0.0;
7311 #ifdef OOMPH_HAS_TRIANGLE_LIB
7312 #ifdef OOMPH_HAS_MPI
7317 template<
class ELEMENT>
7322 if (this->is_mesh_distributed())
7325 const unsigned nboundary = this->nboundary();
7326 dump_file << nboundary
7327 <<
" # number of original boundaries" << std::endl;
7330 const unsigned nshared_boundaries = this->nshared_boundaries();
7331 dump_file << nshared_boundaries
7332 <<
" # number of shared boundaries" << std::endl;
7335 const unsigned init_shd_bnd_id = this->initial_shared_boundary_id();
7336 dump_file << init_shd_bnd_id
7337 <<
" # initial shared boundaries id" << std::endl;
7339 const unsigned final_shd_bnd_id = this->final_shared_boundary_id();
7340 dump_file << final_shd_bnd_id
7341 <<
" # final shared boundaries id" << std::endl;
7344 const unsigned nprocs = this->shared_boundaries_ids().size();
7345 dump_file << nprocs <<
" # number of processors" << std::endl;
7349 for (
unsigned ip = 0; ip < nprocs; ip++)
7351 for (
unsigned jp = 0; jp < nprocs; jp++)
7357 const unsigned nshared_boundaries_iproc_jproc =
7358 this->shared_boundaries_ids(ip, jp).size();
7362 dump_file << nshared_boundaries_iproc_jproc
7363 <<
" # number of shared boundaries with in two "
7364 <<
"processors" << std::endl;
7365 for (
unsigned is = 0;
is < nshared_boundaries_iproc_jproc;
is++)
7367 const unsigned shared_boundary_id =
7368 this->shared_boundaries_ids(ip, jp,
is);
7369 dump_file << ip <<
" " << jp <<
" " << shared_boundary_id
7370 <<
" # ip jp shared_boundary of processors ip and jp"
7383 const unsigned nshared_boundaries_overlap_internal_boundaries =
7384 this->nshared_boundary_overlaps_internal_boundary();
7385 dump_file << nshared_boundaries_overlap_internal_boundaries
7386 <<
" # number of shared boundaries that overlap internal "
7387 <<
"boundaries" << std::endl;
7389 if (nshared_boundaries_overlap_internal_boundaries > 0)
7391 for (
unsigned isb = init_shd_bnd_id; isb < final_shd_bnd_id; isb++)
7395 if (this->shared_boundary_overlaps_internal_boundary(isb))
7399 const unsigned overlapped_internal_boundary =
7400 shared_boundary_overlapping_internal_boundary(isb);
7402 dump_file << isb <<
" " << overlapped_internal_boundary
7403 <<
" # the shared boundary overlaps the internal "
7404 <<
"boundary " << std::endl;
7415 for (
unsigned b = 0; b < nboundary; b++)
7420 if (Assigned_segments_initial_zeta_values[b])
7424 dump_file <<
"1 # assigned boundary coordinates initial zeta values"
7431 Vector<double> initial_coordinates=this->boundary_initial_coordinate(b);
7433 Vector<double> final_coordinates=this->boundary_final_coordinate(b);
7435 dump_file << std::setprecision(14)
7436 << initial_coordinates[0] <<
" " << initial_coordinates[1]
7437 <<
" # initial coordinates for the current boundary"
7440 dump_file << std::setprecision(14)
7441 << final_coordinates[0] <<
" " << final_coordinates[1]
7442 <<
" # final coordinates for the current boundary"
7449 const unsigned zeta_size =
7450 this->boundary_initial_zeta_coordinate(b).size();
7454 std::ostringstream error_message;
7456 <<
"The dimension for the zeta values container is different\n"
7457 <<
"from 1, the current implementation only supports\n"
7458 <<
"one-dimensioned zeta containers\n\n";
7459 throw OomphLibError(error_message.str(),
7460 "TriangleMesh::dump_distributed_info_for_restart()",
7461 OOMPH_EXCEPTION_LOCATION);
7465 Vector<double> zeta_initial = this->boundary_initial_zeta_coordinate(b);
7466 Vector<double> zeta_final = this->boundary_final_zeta_coordinate(b);
7468 dump_file << std::setprecision(14)
7470 <<
" # initial zeta value for the current boundary"
7473 dump_file << std::setprecision(14)
7475 <<
" # final zeta value for the current boundary"
7479 const unsigned nsegments = this->nboundary_segment(b);
7481 dump_file << b <<
" " << nsegments
7482 <<
" # of segments for the current boundary"
7486 for (
unsigned is = 0;
is < nsegments;
is++)
7489 Vector<double> initial_segment_coordinates =
7490 this->boundary_segment_initial_coordinate(b)[
is];
7491 Vector<double> final_segment_coordinates =
7492 this->boundary_segment_final_coordinate(b)[
is];
7494 dump_file << std::setprecision(14)
7495 << initial_segment_coordinates[0] <<
" "
7496 << initial_segment_coordinates[1]
7497 <<
" # initial segment coordinates for the current boundary"
7500 dump_file << std::setprecision(14)
7501 << final_segment_coordinates[0] <<
" "
7502 << final_segment_coordinates[1]
7503 <<
" # final segment coordinates for the current boundary"
7508 if (this->boundary_geom_object_pt(b)!=0)
7510 const double zeta_segment_initial =
7511 this->boundary_segment_initial_zeta(b)[
is];
7512 const double zeta_segment_final =
7513 this->boundary_segment_final_zeta(b)[
is];
7515 dump_file << std::setprecision(14)
7516 << zeta_segment_initial
7517 <<
" # initial segment zeta value for the current boundary"
7520 dump_file << std::setprecision(14)
7521 << zeta_segment_final
7522 <<
" # final segment zeta value for the current boundary"
7527 const double arclength_segment_initial =
7528 this->boundary_segment_initial_arclength(b)[
is];
7529 const double arclength_segment_final =
7530 this->boundary_segment_final_arclength(b)[
is];
7532 dump_file << std::setprecision(14)
7533 << arclength_segment_initial
7534 <<
" # initial segment arclength for the current boundary"
7537 dump_file << std::setprecision(14)
7538 << arclength_segment_final
7539 <<
" # final segment arclength for the current boundary"
7551 dump_file <<
"0 # assigned boundary coordinates initial zeta values"
7564 template<
class ELEMENT>
7569 if (this->is_mesh_distributed())
7572 const unsigned n_boundary = read_unsigned_line_helper(restart_file);
7575 if (n_boundary != this->nboundary())
7577 std::ostringstream error_message;
7579 <<
"The number of boundaries (" << n_boundary <<
") on the "
7580 <<
"file used for restarting is different\nfrom the number of "
7581 <<
"boundaries ("<< this->nboundary() <<
") on the current "
7583 throw OomphLibError(error_message.str(),
7584 "TriangleMesh::read_distributed_info_for_restart()",
7585 OOMPH_EXCEPTION_LOCATION);
7590 unsigned n_shared_boundaries =
7591 read_unsigned_line_helper(restart_file);
7594 n_shared_boundaries++;
7595 n_shared_boundaries--;
7598 unsigned init_shd_bnd_id = read_unsigned_line_helper(restart_file);
7604 unsigned final_shd_bnd_id = read_unsigned_line_helper(restart_file);
7612 const unsigned n_procs = read_unsigned_line_helper(restart_file);
7615 if (
static_cast<int>(n_procs) != this->communicator_pt()->nproc())
7617 std::ostringstream error_message;
7619 <<
"The number of previously used processors ("<< n_procs
7620 <<
") (read from the restart file) is different\nfrom the "
7621 <<
"number of current used processors ("
7622 << this->communicator_pt()->nproc() <<
")\n\n";
7623 throw OomphLibError(error_message.str(),
7624 "TriangleMesh::read_distributed_info_for_restart()",
7625 OOMPH_EXCEPTION_LOCATION);
7630 this->shared_boundaries_ids().clear();
7631 this->shared_boundary_from_processors().clear();
7632 this->shared_boundary_overlaps_internal_boundary().clear();
7636 this->shared_boundaries_ids().resize(n_procs);
7640 for (
unsigned ip = 0; ip < n_procs; ip++)
7644 this->shared_boundaries_ids(ip).resize(n_procs);
7645 for (
unsigned jp = 0; jp < n_procs; jp++)
7651 const unsigned nshared_boundaries_iproc_jproc =
7652 read_unsigned_line_helper(restart_file);
7653 for (
unsigned is = 0;
is < nshared_boundaries_iproc_jproc;
is++)
7657 restart_file >> tmp_ip;
7659 restart_file >> tmp_jp;
7663 const unsigned shared_boundary_id =
7664 read_unsigned_line_helper(restart_file);
7668 this->shared_boundaries_ids(ip, jp).
7669 push_back(shared_boundary_id);
7673 Vector<unsigned> processors(2);
7676 this->shared_boundary_from_processors()[shared_boundary_id] =
7689 const unsigned nshared_boundaries_overlap_internal_boundaries =
7690 read_unsigned_line_helper(restart_file);
7692 for (
unsigned isb = 0;
7693 isb < nshared_boundaries_overlap_internal_boundaries;
7697 unsigned shared_boundary_overlapping;
7698 restart_file >> shared_boundary_overlapping;
7700 const unsigned overlapped_internal_boundary =
7701 read_unsigned_line_helper(restart_file);
7705 this->shared_boundary_overlaps_internal_boundary()
7706 [shared_boundary_overlapping] = overlapped_internal_boundary;
7714 for (
unsigned b = 0; b < n_boundary; b++)
7718 const unsigned boundary_coordinates_initial_zeta_values_assigned =
7719 read_unsigned_line_helper(restart_file);
7721 if (boundary_coordinates_initial_zeta_values_assigned)
7726 Boundary_initial_coordinate[b].clear();
7727 Boundary_final_coordinate[b].clear();
7729 Boundary_initial_zeta_coordinate[b].clear();
7730 Boundary_final_zeta_coordinate[b].clear();
7733 Boundary_segment_inverted[b].clear();
7734 Boundary_segment_initial_coordinate[b].clear();
7735 Boundary_segment_final_coordinate[b].clear();
7737 Boundary_segment_initial_zeta[b].clear();
7738 Boundary_segment_final_zeta[b].clear();
7740 Boundary_segment_initial_arclength[b].clear();
7741 Boundary_segment_final_arclength[b].clear();
7747 Vector<double> initial_coordinates(2);
7750 restart_file >> initial_coordinates[0] >> initial_coordinates[1];
7753 restart_file.ignore(80,
'\n');
7755 Vector<double> final_coordinates(2);
7758 restart_file >> final_coordinates[0] >> final_coordinates[1];
7761 restart_file.ignore(80,
'\n');
7766 this->boundary_initial_coordinate(b)=initial_coordinates;
7767 this->boundary_final_coordinate(b)=final_coordinates;
7770 Vector<double> zeta_initial(1);
7771 restart_file >> zeta_initial[0];
7774 restart_file.ignore(80,
'\n');
7776 Vector<double> zeta_final(1);
7777 restart_file >> zeta_final[0];
7780 restart_file.ignore(80,
'\n');
7783 this->boundary_initial_zeta_coordinate(b) = zeta_initial;
7784 this->boundary_final_zeta_coordinate(b) = zeta_final;
7787 unsigned current_boundary;
7788 restart_file >> current_boundary;
7791 if (current_boundary != b)
7793 std::ostringstream error_message;
7795 <<
"The current boundary id from the restart file ("
7796 << current_boundary <<
") is different from\nthe boundary id "
7797 << b <<
"currently used to re-establish the initial and\nfinal "
7798 <<
"segment's zeta values\n\n";
7799 throw OomphLibError(error_message.str(),
7800 "TriangleMesh::read_distributed_info_for_restart()",
7801 OOMPH_EXCEPTION_LOCATION);
7807 restart_file >> nsegments;
7810 restart_file.ignore(80,
'\n');
7815 for (
unsigned is = 0;
is < nsegments;
is++)
7818 Vector<double> initial_segment_coordinates(2);
7821 restart_file >> initial_segment_coordinates[0]
7822 >> initial_segment_coordinates[1];
7825 restart_file.ignore(80,
'\n');
7827 Vector<double> final_segment_coordinates(2);
7830 restart_file >> final_segment_coordinates[0]
7831 >> final_segment_coordinates[1];
7834 restart_file.ignore(80,
'\n');
7837 this->boundary_segment_initial_coordinate(b).push_back(
7838 initial_segment_coordinates);
7839 this->boundary_segment_final_coordinate(b).push_back(
7840 final_segment_coordinates);
7843 if (this->boundary_geom_object_pt(b)!=0)
7845 Vector<double> zeta_segment_initial(1);
7846 restart_file >> zeta_segment_initial[0];
7849 restart_file.ignore(80,
'\n');
7851 Vector<double> zeta_segment_final(1);
7852 restart_file >> zeta_segment_final[0];
7855 restart_file.ignore(80,
'\n');
7858 this->boundary_segment_initial_zeta(b).push_back(
7859 zeta_segment_initial[0]);
7860 this->boundary_segment_final_zeta(b).push_back(
7861 zeta_segment_final[0]);
7865 Vector<double> arclength_segment_initial(1);
7866 restart_file >> arclength_segment_initial[0];
7869 restart_file.ignore(80,
'\n');
7871 Vector<double> arclength_segment_final(1);
7872 restart_file >> arclength_segment_final[0];
7875 restart_file.ignore(80,
'\n');
7878 this->boundary_segment_initial_arclength(b).push_back(
7879 arclength_segment_initial[0]);
7880 this->boundary_segment_final_arclength(b).push_back(
7881 arclength_segment_final[0]);
7894 #endif // #ifdef OOMPH_HAS_MPI
7895 #endif // #ifdef OOMPH_HAS_TRIANGLE_LIB
7901 template<
class ELEMENT>
7903 std::ostream &outfile)
7912 std::set<Node*> boundary_nodes_pt;
7913 const unsigned n_boundary_ele = this->nboundary_element(b);
7914 for (
unsigned e = 0; e < n_boundary_ele; e++)
7917 FiniteElement* bulk_ele_pt = this->boundary_element_pt(b, e);
7918 #ifdef OOMPH_HAS_MPI
7920 if (!bulk_ele_pt->is_halo())
7924 int face_index = this->face_index_at_boundary(b, e);
7926 FiniteElement* face_ele_pt =
new DummyFaceElement<ELEMENT> (
7927 bulk_ele_pt, face_index);
7930 const unsigned n_nodes = face_ele_pt->nnode();
7931 for (
unsigned i = 0; i < n_nodes; i++)
7934 Node* tmp_node_pt = face_ele_pt->node_pt(i);
7936 boundary_nodes_pt.insert(tmp_node_pt);
7942 #ifdef OOMPH_HAS_MPI
7948 outfile <<
"ZONE T=\"Boundary nodes" << b <<
"\"\n";
7950 std::set<Vector<double> > set_node_coord;
7952 for (std::set<Node*>::iterator it = boundary_nodes_pt.begin();
7953 it != boundary_nodes_pt.end(); it++)
7955 Node *inode_pt = (*it);
7958 const unsigned n_dim = inode_pt->ndim();
7959 Vector<double> node_coord(n_dim+1);
7962 Vector<double> zeta(1);
7963 inode_pt->get_coordinates_on_boundary(b, zeta);
7964 node_coord[0] = zeta[0];
7965 for (
unsigned j = 0; j < n_dim; j++)
7967 node_coord[j+1] = inode_pt->x(j);
7969 set_node_coord.insert(node_coord);
7972 for (std::set<Vector<double> >::iterator it = set_node_coord.begin();
7973 it != set_node_coord.end(); it++)
7976 Vector<double> node_coord = (*it);
7979 const unsigned n_dim = node_coord.size()-1;
7980 for (
unsigned j = 0; j < n_dim; j++)
7982 outfile << node_coord[j+1] <<
" ";
7985 outfile <<
"0.0" << std::endl;
7989 outfile <<
"ZONE T=\"Boundary coordinates " << b <<
"\"\n";
7990 for (std::set<Vector<double> >::iterator it = set_node_coord.begin();
7991 it != set_node_coord.end(); it++)
7994 Vector<double> node_coord = (*it);
7997 const unsigned n_dim = node_coord.size()-1;
7998 for (
unsigned j = 0; j < n_dim; j++)
8000 outfile << node_coord[j+1] <<
" ";
8004 outfile << node_coord[0] << std::endl;
8009 #ifdef OOMPH_HAS_MPI
8016 template<
class ELEMENT>
8018 Vector<TriangleMeshPolygon *> &polygons_pt,
8019 Vector<TriangleMeshOpenCurve*> &open_curves_pt)
8027 const unsigned my_rank = this->communicator_pt()->my_rank();
8041 Vector<TriangleMeshPolyLine *> unsorted_outer_polyline_pt;
8046 Vector<Vector<TriangleMeshPolyLine *> > sorted_outer_curves_pt;
8049 const unsigned nouter=this->Outer_boundary_pt.size();
8050 for (
unsigned i = 0; i < nouter; i++)
8052 const unsigned npolylines = this->Outer_boundary_pt[i]->npolyline();
8053 for (
unsigned p = 0; p < npolylines; p++)
8056 TriangleMeshPolyLine *tmp_polyline_pt =
8057 this->Outer_boundary_pt[i]->polyline_pt(p);
8058 const unsigned nvertex = tmp_polyline_pt->nvertex();
8064 const unsigned bound_id = tmp_polyline_pt->boundary_id();
8065 if (!boundary_was_splitted(bound_id))
8067 unsorted_outer_polyline_pt.push_back(tmp_polyline_pt);
8072 Vector<TriangleMeshPolyLine*> tmp_vector_polylines =
8073 boundary_subpolylines(bound_id);
8074 const unsigned nsub_poly = tmp_vector_polylines.size();
8078 std::ostringstream error_message;
8080 <<
"The boundary ("<<bound_id<<
") was marked to be splitted but\n"
8081 <<
"there are only ("<<nsub_poly<<
") polylines to represent it.\n";
8082 throw OomphLibError(error_message.str(),
8083 OOMPH_CURRENT_FUNCTION,
8084 OOMPH_EXCEPTION_LOCATION);
8089 for (
unsigned isub = 0; isub < nsub_poly; isub++)
8091 unsorted_outer_polyline_pt.push_back(tmp_vector_polylines[isub]);
8093 const unsigned nsvertex = tmp_vector_polylines[isub]->nvertex();
8096 std::ostringstream error_message;
8098 <<
"The current chunk ("<< isub <<
") of the polyline with\n"
8099 <<
"boundary id (" << bound_id <<
") has no vertices\n";
8100 throw OomphLibError(error_message.str(),
8101 OOMPH_CURRENT_FUNCTION,
8102 OOMPH_EXCEPTION_LOCATION);
8104 #endif // #ifdef PARANOID
8112 unsigned nunsorted_outer_polyline = unsorted_outer_polyline_pt.size();
8113 if (nunsorted_outer_polyline > 0)
8118 sort_polylines_helper(unsorted_outer_polyline_pt, sorted_outer_curves_pt);
8129 Vector<TriangleMeshPolyLine *> unsorted_internal_closed_polyline_pt;
8134 Vector<Vector<TriangleMeshPolyLine *> > sorted_internal_closed_curves_pt;
8137 const unsigned ninternal_closed=this->Internal_polygon_pt.size();
8138 for (
unsigned i = 0; i < ninternal_closed; i++)
8140 const unsigned npolylines = this->Internal_polygon_pt[i]->npolyline();
8141 for (
unsigned p = 0; p < npolylines; p++)
8144 TriangleMeshPolyLine *tmp_polyline_pt =
8145 this->Internal_polygon_pt[i]->polyline_pt(p);
8146 const unsigned nvertex = tmp_polyline_pt->nvertex();
8152 const unsigned bound_id = tmp_polyline_pt->boundary_id();
8153 if (!boundary_was_splitted(bound_id))
8155 unsorted_internal_closed_polyline_pt.push_back(tmp_polyline_pt);
8160 Vector<TriangleMeshPolyLine*> tmp_vector_polylines =
8161 boundary_subpolylines(bound_id);
8162 const unsigned nsub_poly = tmp_vector_polylines.size();
8166 std::ostringstream error_message;
8168 <<
"The boundary ("<<bound_id<<
") was marked to be splitted but\n"
8169 <<
"there are only ("<<nsub_poly<<
") polylines to represent it.\n";
8170 throw OomphLibError(error_message.str(),
8171 OOMPH_CURRENT_FUNCTION,
8172 OOMPH_EXCEPTION_LOCATION);
8177 for (
unsigned isub = 0; isub < nsub_poly; isub++)
8179 unsorted_internal_closed_polyline_pt.push_back(tmp_vector_polylines[isub]);
8181 const unsigned nsvertex = tmp_vector_polylines[isub]->nvertex();
8184 std::ostringstream error_message;
8186 <<
"The current chunk ("<< isub <<
") of the polyline with\n"
8187 <<
"boundary id (" << bound_id <<
") has no vertices\n";
8188 throw OomphLibError(error_message.str(),
8189 OOMPH_CURRENT_FUNCTION,
8190 OOMPH_EXCEPTION_LOCATION);
8192 #endif // #ifdef PARANOID
8199 const unsigned nunsorted_internal_closed_polyline =
8200 unsorted_internal_closed_polyline_pt.size();
8202 if (nunsorted_internal_closed_polyline > 0)
8206 sort_polylines_helper(unsorted_internal_closed_polyline_pt,
8207 sorted_internal_closed_curves_pt);
8217 Vector<TriangleMeshPolyLine *> unsorted_internal_open_polyline_pt;
8222 Vector<Vector<TriangleMeshPolyLine *> > sorted_internal_open_curves_pt;
8225 const unsigned ninternal_open = this->Internal_open_curve_pt.size();
8226 for (
unsigned i = 0; i < ninternal_open; i++)
8228 const unsigned ncurve_section =
8229 this->Internal_open_curve_pt[i]->ncurve_section();
8230 for (
unsigned p = 0; p < ncurve_section; p++)
8233 TriangleMeshPolyLine *tmp_polyline_pt =
8234 this->Internal_open_curve_pt[i]->polyline_pt(p);
8235 const unsigned nvertex = tmp_polyline_pt->nvertex();
8241 const unsigned bound_id = tmp_polyline_pt->boundary_id();
8242 if (!boundary_was_splitted(bound_id))
8246 if (!boundary_marked_as_shared_boundary(bound_id, 0))
8248 unsorted_internal_open_polyline_pt.push_back(tmp_polyline_pt);
8254 Vector<TriangleMeshPolyLine*> tmp_vector_polylines =
8255 boundary_subpolylines(bound_id);
8256 const unsigned nsub_poly = tmp_vector_polylines.size();
8260 std::ostringstream error_message;
8262 <<
"The boundary ("<<bound_id<<
") was marked to be splitted but\n"
8263 <<
"there are only ("<<nsub_poly<<
") polylines to represent it.\n";
8264 throw OomphLibError(error_message.str(),
8265 OOMPH_CURRENT_FUNCTION,
8266 OOMPH_EXCEPTION_LOCATION);
8271 for (
unsigned isub = 0; isub < nsub_poly; isub++)
8275 if (!boundary_marked_as_shared_boundary(bound_id, isub))
8277 unsorted_internal_open_polyline_pt.push_back(tmp_vector_polylines[isub]);
8280 const unsigned nsvertex = tmp_vector_polylines[isub]->nvertex();
8283 std::ostringstream error_message;
8285 <<
"The current chunk ("<< isub <<
") of the polyline with\n"
8286 <<
"boundary id (" << bound_id <<
") has no vertices\n";
8287 throw OomphLibError(error_message.str(),
8288 OOMPH_CURRENT_FUNCTION,
8289 OOMPH_EXCEPTION_LOCATION);
8291 #endif // #ifdef PARANOID
8298 const unsigned nunsorted_internal_open_polyline =
8299 unsorted_internal_open_polyline_pt.size();
8301 if (nunsorted_internal_open_polyline > 0)
8305 sort_polylines_helper(unsorted_internal_open_polyline_pt,
8306 sorted_internal_open_curves_pt);
8314 Vector<TriangleMeshPolyLine *> unsorted_shared_polyline_pt;
8318 Vector<TriangleMeshPolyLine *> unsorted_shared_to_internal_polyline_pt;
8323 Vector<Vector<TriangleMeshPolyLine *> > sorted_shared_curves_pt;
8326 const unsigned ncurves = nshared_boundary_curves(my_rank);
8327 for (
unsigned i = 0; i < ncurves; i++)
8329 const unsigned npolylines = nshared_boundary_polyline(my_rank, i);
8330 for (
unsigned p = 0; p < npolylines; p++)
8332 const unsigned nvertex =
8333 shared_boundary_polyline_pt(my_rank, i, p)->nvertex();
8336 TriangleMeshPolyLine *tmp_shared_poly_pt =
8337 shared_boundary_polyline_pt(my_rank, i, p);
8341 if (this->nshared_boundary_overlaps_internal_boundary() > 0)
8344 const unsigned shd_bnd_id = tmp_shared_poly_pt->boundary_id();
8348 if (this->shared_boundary_overlaps_internal_boundary(shd_bnd_id))
8350 unsorted_shared_to_internal_polyline_pt.push_back(
8351 tmp_shared_poly_pt);
8354 unsorted_shared_polyline_pt.push_back(tmp_shared_poly_pt);
8360 const unsigned nunsorted_shared_polyline =
8361 unsorted_shared_polyline_pt.size();
8363 if (nunsorted_shared_polyline > 0)
8367 sort_polylines_helper(unsorted_shared_polyline_pt, sorted_shared_curves_pt);
8377 const unsigned nouter_curves = sorted_outer_curves_pt.size();
8378 const unsigned ninternal_closed_curves =
8379 sorted_internal_closed_curves_pt.size();
8380 const unsigned nshared_curves = sorted_shared_curves_pt.size();
8381 const unsigned ntotal_curves = nouter_curves +
8382 ninternal_closed_curves +
8386 unsigned counter = 0;
8387 Vector<Vector<TriangleMeshPolyLine *> > all_curves_pt(ntotal_curves);
8391 for (
unsigned i = 0; i < nshared_curves; i++,counter++)
8393 all_curves_pt[counter] = sorted_shared_curves_pt[i];
8397 for (
unsigned i = 0; i < ninternal_closed_curves; i++,counter++)
8399 all_curves_pt[counter] = sorted_internal_closed_curves_pt[i];
8403 for (
unsigned i = 0; i < nouter_curves; i++,counter++)
8405 all_curves_pt[counter] = sorted_outer_curves_pt[i];
8410 this->create_tmp_polygons_helper(all_curves_pt,polygons_pt);
8412 this->create_tmp_open_curves_helper(sorted_internal_open_curves_pt,
8413 unsorted_shared_to_internal_polyline_pt,
8427 this->create_shared_polylines_connections();
8438 Vector<Vector<double> > new_holes_coordinates;
8444 const unsigned n_holes = this->Internal_polygon_pt.size();
8445 for (
unsigned h = 0; h < n_holes; h++)
8447 Vector<double> hole_coordinates =
8448 this->Internal_polygon_pt[h]->internal_point();
8450 if (!hole_coordinates.empty())
8452 new_holes_coordinates.push_back(hole_coordinates);
8458 if (First_time_compute_holes_left_by_halo_elements)
8461 const unsigned n_extra_holes = Extra_holes_coordinates.size();
8462 for (
unsigned h = 0; h < n_extra_holes; h++)
8464 Vector<double> hole_coordinates = Extra_holes_coordinates[h];
8465 new_holes_coordinates.push_back(hole_coordinates);
8469 Original_extra_holes_coordinates = Extra_holes_coordinates;
8472 First_time_compute_holes_left_by_halo_elements =
false;
8479 const unsigned n_original_extra_holes =
8480 Original_extra_holes_coordinates.size();
8481 for (
unsigned h = 0; h < n_original_extra_holes; h++)
8483 Vector<double> hole_coordinates = Original_extra_holes_coordinates[h];
8484 new_holes_coordinates.push_back(hole_coordinates);
8490 compute_holes_left_by_halo_elements_helper(new_holes_coordinates);
8494 update_holes_information_helper(polygons_pt, new_holes_coordinates);
8500 Extra_holes_coordinates = new_holes_coordinates;
8513 template<
class ELEMENT>
8517 Vector<TriangleMeshPolygon *> &polygons_pt)
8529 const unsigned ncurves = polylines_pt.size();
8532 const unsigned nunsorted_curves = ncurves;
8534 unsigned nsorted_curves = 0;
8537 std::vector<bool> done_curve(ncurves);
8542 std::list<Vector<TriangleMeshPolyLine*> > list_building_polygon_pt;
8545 bool root_curve_found =
false;
8550 unsigned root_curve_idx = 0;
8553 for (
unsigned ic = 0; ic < ncurves; ic++)
8555 if (!done_curve[ic])
8557 root_curve_idx = ic;
8560 root_curve_found =
true;
8562 done_curve[ic] =
true;
8569 if (!root_curve_found)
8571 std::stringstream err;
8572 err <<
"The root curve to create a polygon from the shared and "
8573 <<
"original boundaries was not found!!!\n";
8574 throw OomphLibError(err.str(),
8575 "TriangleMesh::create_tmp_polygons_helper()",
8576 OOMPH_EXCEPTION_LOCATION);
8581 Vector<TriangleMeshPolyLine*> root_curve_pt=polylines_pt[root_curve_idx];
8584 list_building_polygon_pt.push_back(root_curve_pt);
8587 Vector<double> root_curve_initial_vertex(2);
8588 Vector<double> root_curve_final_vertex(2);
8591 const unsigned nroot_curve_polyline = root_curve_pt.size();
8593 root_curve_pt[0]->initial_vertex_coordinate(root_curve_initial_vertex);
8594 root_curve_pt[nroot_curve_polyline-1]->
8595 final_vertex_coordinate(root_curve_final_vertex);
8599 ((root_curve_initial_vertex[0] - root_curve_final_vertex[0])*
8600 (root_curve_initial_vertex[0] - root_curve_final_vertex[0]))
8602 ((root_curve_initial_vertex[1] - root_curve_final_vertex[1])*
8603 (root_curve_initial_vertex[1] - root_curve_final_vertex[1]));
8605 if (diff < ToleranceForVertexMismatchInPolygons::Tolerable_error)
8609 Vector<TriangleMeshCurveSection*>
8610 curve_section_pt(nroot_curve_polyline);
8613 for (
unsigned i = 0; i < nroot_curve_polyline; i++)
8614 {curve_section_pt[i] = root_curve_pt[i];}
8617 TriangleMeshPolygon *new_polygon_pt =
8618 new TriangleMeshPolygon(curve_section_pt);
8621 this->Free_polygon_pt.insert(new_polygon_pt);
8624 polygons_pt.push_back(new_polygon_pt);
8631 bool added_curve =
false;
8636 bool polygon_created =
false;
8640 added_curve =
false;
8643 for (
unsigned ic = root_curve_idx+1; ic < ncurves; ic++)
8645 if (!done_curve[ic])
8648 Vector<TriangleMeshPolyLine*> current_curve_pt =
8653 const unsigned ncurrent_curve_polyline = current_curve_pt.size();
8657 Vector<double> current_curve_initial_vertex(2);
8658 Vector<double> current_curve_final_vertex(2);
8660 current_curve_pt[0]->
8661 initial_vertex_coordinate(current_curve_initial_vertex);
8662 current_curve_pt[ncurrent_curve_polyline-1]->
8663 final_vertex_coordinate(current_curve_final_vertex);
8669 ((current_curve_final_vertex[0] - root_curve_initial_vertex[0])*
8670 (current_curve_final_vertex[0] - root_curve_initial_vertex[0]))
8672 ((current_curve_final_vertex[1] - root_curve_initial_vertex[1])*
8673 (current_curve_final_vertex[1] - root_curve_initial_vertex[1]));
8676 if (diff < ToleranceForVertexMismatchInPolygons::Tolerable_error)
8679 list_building_polygon_pt.push_front(current_curve_pt);
8681 done_curve[ic] =
true;
8683 root_curve_initial_vertex[0] = current_curve_initial_vertex[0];
8684 root_curve_initial_vertex[1] = current_curve_initial_vertex[1];
8693 ((current_curve_initial_vertex[0] - root_curve_initial_vertex[0])*
8694 (current_curve_initial_vertex[0] - root_curve_initial_vertex[0]))
8696 ((current_curve_initial_vertex[1] - root_curve_initial_vertex[1])*
8697 (current_curve_initial_vertex[1] - root_curve_initial_vertex[1]));
8700 if (diff < ToleranceForVertexMismatchInPolygons::Tolerable_error)
8702 Vector<TriangleMeshPolyLine*>
8703 tmp_curve_pt(ncurrent_curve_polyline);
8705 for (
unsigned it = 0; it < ncurrent_curve_polyline; it++)
8707 current_curve_pt[it]->reverse();
8708 tmp_curve_pt[it] = current_curve_pt[it];
8712 for (
int i = ncurrent_curve_polyline - 1; i >= 0; i--,count++)
8713 {current_curve_pt[count] = tmp_curve_pt[i];}
8715 list_building_polygon_pt.push_front(current_curve_pt);
8717 done_curve[ic] =
true;
8719 root_curve_initial_vertex[0] = current_curve_final_vertex[0];
8720 root_curve_initial_vertex[1] = current_curve_final_vertex[1];
8729 ((current_curve_initial_vertex[0] - root_curve_final_vertex[0])*
8730 (current_curve_initial_vertex[0] - root_curve_final_vertex[0]))
8732 ((current_curve_initial_vertex[1] - root_curve_final_vertex[1])*
8733 (current_curve_initial_vertex[1] - root_curve_final_vertex[1]));
8736 if (diff < ToleranceForVertexMismatchInPolygons::Tolerable_error)
8739 list_building_polygon_pt.push_back(current_curve_pt);
8741 done_curve[ic] =
true;
8743 root_curve_final_vertex[0] = current_curve_final_vertex[0];
8744 root_curve_final_vertex[1] = current_curve_final_vertex[1];
8753 ((current_curve_final_vertex[0] - root_curve_final_vertex[0])*
8754 (current_curve_final_vertex[0] - root_curve_final_vertex[0]))
8756 ((current_curve_final_vertex[1] - root_curve_final_vertex[1])*
8757 (current_curve_final_vertex[1] - root_curve_final_vertex[1]));
8760 if (diff < ToleranceForVertexMismatchInPolygons::Tolerable_error)
8762 Vector<TriangleMeshPolyLine*>
8763 tmp_curve_pt(ncurrent_curve_polyline);
8765 for (
unsigned it = 0; it < ncurrent_curve_polyline; it++)
8767 current_curve_pt[it]->reverse();
8768 tmp_curve_pt[it] = current_curve_pt[it];
8772 for (
int i = ncurrent_curve_polyline - 1; i >= 0; i--,count++)
8773 {current_curve_pt[count] = tmp_curve_pt[i];}
8775 list_building_polygon_pt.push_back(current_curve_pt);
8777 done_curve[ic] =
true;
8779 root_curve_final_vertex[0] = current_curve_initial_vertex[0];
8780 root_curve_final_vertex[1] = current_curve_initial_vertex[1];
8794 ((root_curve_initial_vertex[0] - root_curve_final_vertex[0])*
8795 (root_curve_initial_vertex[0] - root_curve_final_vertex[0]))
8797 ((root_curve_initial_vertex[1] - root_curve_final_vertex[1])*
8798 (root_curve_initial_vertex[1] - root_curve_final_vertex[1]));
8800 if (diff < ToleranceForVertexMismatchInPolygons::Tolerable_error)
8804 added_curve =
false;
8807 polygon_created =
true;
8813 }
while(added_curve);
8816 if (!polygon_created)
8818 std::stringstream error_message;
8820 <<
"It was no possible to create a TriangleMeshPolygon with "
8821 <<
"the input set of curves\n"
8822 <<
"These are the initial and final vertices in the current "
8823 <<
"sorted list of\nTriangleMeshPolyLines\n\n";
8824 Vector<double> init_vertex(2);
8825 Vector<double> final_vertex(2);
8826 unsigned icurve = 0;
8827 for (std::list<Vector<TriangleMeshPolyLine*> >::iterator it
8828 = list_building_polygon_pt.begin();
8829 it != list_building_polygon_pt.end(); it++, icurve++)
8831 const unsigned ncurrent_curve_polyline = (*it).size();
8833 <<
"TriangleMeshCurve #" << icurve <<
"\n"
8834 <<
"-----------------------------------\n";
8835 for (
unsigned ip = 0; ip < ncurrent_curve_polyline; ip++)
8837 Vector<double> init_vertex(2);
8838 Vector<double> final_vertex(2);
8839 (*it)[ip]->initial_vertex_coordinate(init_vertex);
8840 (*it)[ip]->final_vertex_coordinate(final_vertex);
8842 <<
"TriangleMeshPolyLine #" << ip <<
"\n"
8843 <<
"Initial vertex: ("<<init_vertex[0]<<
","<<init_vertex[1]<<
")\n"
8844 <<
"Final vertex: ("<<final_vertex[0]<<
","<<final_vertex[1]<<
")\n";
8848 throw OomphLibError(error_message.str(),
8849 "TriangleMesh::create_tmp_polygons_helper()",
8850 OOMPH_EXCEPTION_LOCATION);
8856 unsigned ntotal_polylines = 0;
8858 for (std::list<Vector<TriangleMeshPolyLine*> >::iterator it
8859 = list_building_polygon_pt.begin();
8860 it != list_building_polygon_pt.end(); it++)
8862 ntotal_polylines+=(*it).size();
8866 Vector<TriangleMeshCurveSection*> curve_section_pt(ntotal_polylines);
8869 unsigned counter = 0;
8870 for (std::list<Vector<TriangleMeshPolyLine*> >::iterator it
8871 = list_building_polygon_pt.begin();
8872 it != list_building_polygon_pt.end(); it++)
8874 const unsigned ncurrent_curve_polyline = (*it).size();
8875 for (
unsigned ip = 0; ip < ncurrent_curve_polyline; ip++,counter++)
8877 curve_section_pt[counter] = (*it)[ip];
8882 TriangleMeshPolygon *new_polygon_pt =
8883 new TriangleMeshPolygon(curve_section_pt);
8886 this->Free_polygon_pt.insert(new_polygon_pt);
8889 polygons_pt.push_back(new_polygon_pt);
8894 }
while(nsorted_curves < nunsorted_curves);
8903 template<
class ELEMENT>
8905 Vector<Vector<TriangleMeshPolyLine *> > &sorted_open_curves_pt,
8906 Vector<TriangleMeshPolyLine*> &unsorted_shared_to_internal_poly_pt,
8907 Vector<TriangleMeshOpenCurve *> &open_curves_pt)
8911 const unsigned ninternal_open_curves = sorted_open_curves_pt.size();
8915 for (
unsigned i = 0; i < ninternal_open_curves; i++)
8918 const unsigned npoly = sorted_open_curves_pt[i].size();
8919 Vector<TriangleMeshCurveSection*> tmp_curve_section(npoly);
8920 for (
unsigned j = 0; j < npoly; j++)
8922 tmp_curve_section[j] = sorted_open_curves_pt[i][j];
8925 TriangleMeshOpenCurve *new_open_curve_pt =
8926 new TriangleMeshOpenCurve(tmp_curve_section);
8929 this->Free_open_curve_pt.insert(new_open_curve_pt);
8932 open_curves_pt.push_back(new_open_curve_pt);
8944 template<
class ELEMENT>
8946 std::set<FiniteElement*> &element_in_processor_pt,
8947 const int &root_edge_bnd_id,
8948 std::map<std::pair<Node*,Node*>,
bool> &overlapped_face,
8949 std::map<
unsigned, std::map<Node*, bool> >
8950 &node_on_bnd_not_overlapped_by_shd_bnd,
8951 std::list<Node*> ¤t_polyline_nodes,
8952 std::map<
unsigned, std::list<Node*> >
8953 &shared_bnd_id_to_sorted_list_node_pt,
8954 const unsigned &node_degree,
8956 const bool called_from_load_balance)
8959 int flag_to_return = -1;
8968 bool overlapping_internal_boundary =
false;
8970 unsigned internal_overlaping_bnd_id = 0;
8971 if (root_edge_bnd_id != -1)
8974 overlapping_internal_boundary =
true;
8976 internal_overlaping_bnd_id =
static_cast<unsigned>(root_edge_bnd_id);
8984 if (new_node_pt->is_on_boundary())
8987 bool is_node_living_in_non_overlapped_boundary =
false;
8991 const unsigned noriginal_bnd = this->initial_shared_boundary_id();
8992 for (
unsigned bb=0;bb<noriginal_bnd;bb++)
9000 if (overlapping_internal_boundary)
9003 if (new_node_pt->is_on_boundary(bb))
9009 const bool on_bnd_edge_not_overlapped_by_shd_bnd =
9010 node_on_bnd_not_overlapped_by_shd_bnd[bb][new_node_pt];
9011 if (bb != internal_overlaping_bnd_id ||
9012 ((bb == internal_overlaping_bnd_id) &&
9013 (on_bnd_edge_not_overlapped_by_shd_bnd)))
9016 if (bb != internal_overlaping_bnd_id)
9018 is_node_living_in_non_overlapped_boundary =
true;
9028 const unsigned n_bound_ele = this->nboundary_element(bb);
9029 if (n_bound_ele > 0)
9033 for (
unsigned e = 0; e < n_bound_ele; e++)
9036 FiniteElement* bulk_ele_pt = this->boundary_element_pt(bb, e);
9039 std::set<FiniteElement*>::iterator it =
9040 element_in_processor_pt.find(bulk_ele_pt);
9042 if (it!=element_in_processor_pt.end())
9045 bool found_node =
false;
9047 int face_index = this->face_index_at_boundary(bb, e);
9049 FiniteElement* face_ele_pt =
9050 new DummyFaceElement<ELEMENT>(bulk_ele_pt, face_index);
9052 const unsigned n_node_face = face_ele_pt->nnode();
9054 Node* first_node_pt = face_ele_pt->node_pt(0);
9055 Node* last_node_pt = face_ele_pt->node_pt(n_node_face-1);
9057 std::pair<Node*, Node*> tmp_edge =
9058 std::make_pair(first_node_pt, last_node_pt);
9062 if (!overlapped_face[tmp_edge])
9065 for (
unsigned n = 0; n < n_node_face; n++)
9068 if (face_ele_pt->node_pt(n) == new_node_pt)
9084 flag_to_return = bb;
9085 return flag_to_return;
9104 if (new_node_pt->is_on_boundary(bb))
9113 const unsigned n_bound_ele = this->nboundary_element(bb);
9114 if (n_bound_ele > 0)
9118 for (
unsigned e = 0; e < n_bound_ele; e++)
9121 FiniteElement* bulk_ele_pt = this->boundary_element_pt(bb, e);
9124 std::set<FiniteElement*>::iterator it =
9125 element_in_processor_pt.find(bulk_ele_pt);
9127 if (it!=element_in_processor_pt.end())
9130 bool found_node =
false;
9132 int face_index = this->face_index_at_boundary(bb, e);
9134 FiniteElement* face_ele_pt =
9135 new DummyFaceElement<ELEMENT>(bulk_ele_pt, face_index);
9137 const unsigned n_node_face = face_ele_pt->nnode();
9139 Node* first_node_pt = face_ele_pt->node_pt(0);
9140 Node* last_node_pt = face_ele_pt->node_pt(n_node_face-1);
9142 std::pair<Node*, Node*> tmp_edge =
9143 std::make_pair(first_node_pt, last_node_pt);
9147 if (!overlapped_face[tmp_edge])
9150 for (
unsigned n = 0; n < n_node_face; n++)
9153 if (face_ele_pt->node_pt(n) == new_node_pt)
9169 flag_to_return = bb;
9170 return flag_to_return;
9195 if (!overlapping_internal_boundary)
9200 flag_to_return = -3;
9207 if (is_node_living_in_non_overlapped_boundary)
9209 flag_to_return = -3;
9218 if (flag_to_return >= 0)
9220 return flag_to_return;
9231 Vector<unsigned> candidate_shared_bnd_to_connect;
9233 for (std::map<
unsigned, std::list<Node*> >::iterator it =
9234 shared_bnd_id_to_sorted_list_node_pt.begin();
9235 it != shared_bnd_id_to_sorted_list_node_pt.end();
9241 const unsigned i_bnd_id = (*it).first;
9244 std::list<Node*>::iterator it_list = (*it).second.begin();
9246 const unsigned n_nodes = (*it).second.size();
9248 for (
unsigned i = 0; i < n_nodes; i++, it_list++)
9251 if ((*it_list) == new_node_pt)
9255 candidate_shared_bnd_to_connect.push_back(i_bnd_id);
9266 const unsigned n_candidate_shared_bnd_to_connect =
9267 candidate_shared_bnd_to_connect.size();
9270 if (n_candidate_shared_bnd_to_connect > 0)
9277 if (called_from_load_balance)
9279 return candidate_shared_bnd_to_connect[0];
9289 Vector<unsigned> shared_bound_in_this_proc;
9292 shared_boundaries_in_this_processor(shared_bound_in_this_proc);
9298 const unsigned n_shared_bound_in_this_proc =
9299 shared_bound_in_this_proc.size();
9302 for (
unsigned i = 0; i < n_candidate_shared_bnd_to_connect; i++)
9305 const unsigned i_candidate_shared_bnd =
9306 candidate_shared_bnd_to_connect[i];
9309 for (
unsigned j = 0; j < n_shared_bound_in_this_proc; j++)
9312 if (i_candidate_shared_bnd == shared_bound_in_this_proc[j])
9315 flag_to_return = i_candidate_shared_bnd;
9316 return flag_to_return;
9327 flag_to_return = -3;
9333 if (flag_to_return >= 0)
9335 return flag_to_return;
9344 unsigned nrepeated = 0;
9345 for (std::list<Node*>::iterator it_list = current_polyline_nodes.begin();
9346 it_list != current_polyline_nodes.end();
9351 if ((*it_list) == new_node_pt) {nrepeated++;}
9360 flag_to_return = -2;
9366 if (node_degree > 2)
9368 flag_to_return = -3;
9372 return flag_to_return;
9383 template<
class ELEMENT>
9387 const unsigned my_rank = this->communicator_pt()->my_rank();
9390 Vector<Vector<TriangleMeshPolyLine*> > shared_curves_pt =
9391 this->Shared_boundary_polyline_pt[my_rank];
9395 const unsigned ncurves = shared_curves_pt.size();
9396 for (
unsigned icurve = 0; icurve < ncurves; icurve++)
9399 const unsigned npoly = shared_curves_pt[icurve].size();
9400 for (
unsigned ipoly = 0; ipoly < npoly; ipoly++)
9403 TriangleMeshPolyLine *shd_poly_pt = shared_curves_pt[icurve][ipoly];
9406 const unsigned bound_id = shd_poly_pt->boundary_id();
9409 const bool is_connected_to_the_left =
9410 shd_poly_pt->is_initial_vertex_connected();
9413 const bool is_connected_to_the_right =
9414 shd_poly_pt->is_final_vertex_connected();
9419 if (is_connected_to_the_left || is_connected_to_the_right)
9423 const unsigned n_vertex = shd_poly_pt->nvertex();
9430 if (is_connected_to_the_left)
9434 const unsigned uconnection_to_the_left =
9435 shd_poly_pt->initial_vertex_connected_bnd_id();
9438 TriangleMeshPolyLine *poly_to_connect_pt = 0;
9442 bool connecting_to_an_split_boundary =
false;
9446 bool connecting_to_an_overlaped_boundary =
false;
9449 if (uconnection_to_the_left == bound_id)
9452 poly_to_connect_pt = shd_poly_pt;
9457 const unsigned initial_shd_bnd_id = initial_shared_boundary_id();
9459 if (uconnection_to_the_left >= initial_shd_bnd_id)
9463 poly_to_connect_pt =
9464 boundary_polyline_pt(uconnection_to_the_left);
9472 if (boundary_was_splitted(uconnection_to_the_left))
9474 connecting_to_an_split_boundary =
true;
9484 if (connecting_to_an_split_boundary)
9488 const unsigned n_sub_poly =
9489 nboundary_subpolylines(uconnection_to_the_left);
9494 for (
unsigned ii =0; ii < n_sub_poly; ii++)
9496 if (boundary_marked_as_shared_boundary(
9497 uconnection_to_the_left, ii))
9501 connecting_to_an_overlaped_boundary =
true;
9512 if (boundary_marked_as_shared_boundary(
9513 uconnection_to_the_left, 0))
9517 connecting_to_an_overlaped_boundary =
true;
9524 if (!(connecting_to_an_split_boundary ||
9525 connecting_to_an_overlaped_boundary))
9529 poly_to_connect_pt =
9530 boundary_polyline_pt(uconnection_to_the_left);
9541 if (!connecting_to_an_split_boundary)
9543 if (boundary_was_splitted(uconnection_to_the_left))
9545 std::stringstream error;
9547 <<
"The current shared boundary (" << bound_id <<
") was "
9548 <<
"marked to have a connection\nto the left with the "
9549 <<
"boundary (" << uconnection_to_the_left <<
").\n"
9550 <<
"The problem is that the destination boundary (possibly\n"
9551 <<
"another shared boundary) is marked to be split\n"
9552 <<
"There should not be split shared boundaries\n\n";
9553 throw OomphLibError(
9555 "TriangleMesh::create_shared_polylines_connections()",
9556 OOMPH_EXCEPTION_LOCATION);
9569 Vector<double> shd_bnd_left_vertex =
9570 shd_poly_pt->vertex_coordinate(0);
9573 if (!connecting_to_an_split_boundary)
9577 if (!connecting_to_an_overlaped_boundary)
9581 unsigned vertex_index = 0;
9583 const bool found_vertex_index =
9584 get_connected_vertex_number_on_destination_polyline(
9585 poly_to_connect_pt, shd_bnd_left_vertex, vertex_index);
9589 if (!found_vertex_index)
9591 std::stringstream error;
9593 <<
"The current shared boundary (" << bound_id <<
") was "
9594 <<
"marked to have a connection\nto the left with the "
9595 <<
"boundary (" << uconnection_to_the_left <<
").\n"
9596 <<
"The problem is that the left vertex of the current\n"
9597 <<
"shared boundary is not in the list of vertices of the\n"
9598 <<
"boundary to connect.\n\n"
9599 <<
"This is the left vertex of the current shared boundary\n"
9600 <<
"Left vertex: (" << shd_bnd_left_vertex[0] <<
", "
9601 << shd_bnd_left_vertex[1] <<
")\n\n"
9602 <<
"This is the list of vertices on the destination "
9604 const unsigned n_v = poly_to_connect_pt->nvertex();
9605 for (
unsigned i = 0; i < n_v; i++)
9607 Vector<double> cvertex =
9608 poly_to_connect_pt->vertex_coordinate(i);
9610 <<
"Vertex #"<<i<<
": ("<<cvertex[0]<<
", "<<cvertex[1]<<
")\n";
9612 throw OomphLibError(
9614 "TriangleMesh::create_shared_polylines_connections()",
9615 OOMPH_EXCEPTION_LOCATION);
9621 shd_poly_pt->connect_initial_vertex_to_polyline(
9622 poly_to_connect_pt, vertex_index);
9632 unsigned vertex_index = 0;
9634 bool found_vertex_index =
false;
9638 Vector<unsigned> dst_shd_bnd_ids;
9639 get_shared_boundaries_overlapping_internal_boundary(
9640 uconnection_to_the_left, dst_shd_bnd_ids);
9644 const unsigned n_shd_bnd_overlap_int_bnd =
9645 dst_shd_bnd_ids.size();
9649 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
9652 const unsigned new_connection_to_the_left =
9653 dst_shd_bnd_ids[ss];
9657 poly_to_connect_pt =
9658 boundary_polyline_pt(new_connection_to_the_left);
9660 if (poly_to_connect_pt!=0)
9664 found_vertex_index =
9665 get_connected_vertex_number_on_destination_polyline(
9666 poly_to_connect_pt, shd_bnd_left_vertex, vertex_index);
9671 if (found_vertex_index)
9681 if (!found_vertex_index)
9683 std::stringstream error;
9685 <<
"The current shared boundary (" << bound_id <<
") was "
9686 <<
"marked to have a connection\nto the left with the "
9687 <<
"boundary (" << uconnection_to_the_left <<
").\n"
9688 <<
"This last boundary is marked to be overlaped by "
9689 <<
"shared boundaries\n"
9690 <<
"The problem is that the left vertex of the current\n"
9691 <<
"shared boundary is not in the list of vertices of the\n"
9692 <<
"boundary to connect.\n\n"
9693 <<
"This is the left vertex of the current shared boundary\n"
9694 <<
"Left vertex: (" << shd_bnd_left_vertex[0] <<
", "
9695 << shd_bnd_left_vertex[1] <<
")\n\n"
9696 <<
"This is the list of vertices on the destination "
9698 Vector<unsigned> dst_shd_bnd_ids;
9699 get_shared_boundaries_overlapping_internal_boundary(
9700 uconnection_to_the_left, dst_shd_bnd_ids);
9701 const unsigned n_shd_bnd_overlap_int_bnd =
9702 dst_shd_bnd_ids.size();
9703 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
9705 const unsigned new_connection_to_the_left =
9706 dst_shd_bnd_ids[ss];
9707 poly_to_connect_pt =
9708 boundary_polyline_pt(new_connection_to_the_left);
9709 if (poly_to_connect_pt != 0)
9711 const unsigned shd_bnd_id_overlap =
9712 poly_to_connect_pt->boundary_id();
9713 error <<
"Shared boundary id("
9714 << shd_bnd_id_overlap <<
")\n";
9715 const unsigned n_v = poly_to_connect_pt->nvertex();
9716 for (
unsigned i = 0; i < n_v; i++)
9718 Vector<double> cvertex =
9719 poly_to_connect_pt->vertex_coordinate(i);
9721 <<
"Vertex #"<<i<<
": ("<<cvertex[0]<<
", "
9722 <<cvertex[1]<<
")\n";
9727 throw OomphLibError(
9729 "TriangleMesh::create_shared_polylines_connections()",
9730 OOMPH_EXCEPTION_LOCATION);
9738 shd_poly_pt->connect_initial_vertex_to_polyline(
9739 poly_to_connect_pt, vertex_index);
9750 Vector<TriangleMeshPolyLine*> tmp_vector_subpolylines =
9751 boundary_subpolylines(uconnection_to_the_left);
9754 const unsigned nsub_poly = tmp_vector_subpolylines.size();
9758 std::ostringstream error_message;
9760 <<
"The boundary (" << uconnection_to_the_left <<
") was "
9761 <<
"marked to be splitted but\n"
9762 <<
"there are only ("<<nsub_poly<<
") polylines to "
9763 <<
"represent it.\n";
9764 throw OomphLibError(
9765 error_message.str(),
9766 "TriangleMesh::create_shared_polylines_connections()",
9767 OOMPH_EXCEPTION_LOCATION);
9779 if (!connecting_to_an_overlaped_boundary)
9785 unsigned vertex_index = 0;
9787 unsigned sub_poly_to_connect = 0;
9789 bool found_vertex_index =
false;
9793 for (
unsigned isub = 0; isub < nsub_poly; isub++)
9796 poly_to_connect_pt = tmp_vector_subpolylines[isub];
9798 found_vertex_index =
9799 get_connected_vertex_number_on_destination_polyline(
9800 poly_to_connect_pt, shd_bnd_left_vertex, vertex_index);
9803 if (found_vertex_index)
9807 sub_poly_to_connect = isub;
9815 if (!found_vertex_index)
9817 std::stringstream error;
9819 <<
"The current shared boundary (" << bound_id <<
") was "
9820 <<
"marked to have a connection\nto the left with the "
9821 <<
"boundary (" << uconnection_to_the_left <<
").\n"
9822 <<
"The problem is that the left vertex of the current\n"
9823 <<
"shared boundary is not in the list of vertices of any\n"
9824 <<
"of the sub polylines that represent the boundary to\n"
9826 <<
"This is the left vertex of the current shared boundary\n"
9827 <<
"Left vertex: (" << shd_bnd_left_vertex[0] <<
", "
9828 << shd_bnd_left_vertex[1] <<
")\n\n"
9829 <<
"This is the list of vertices on the destination "
9831 for (
unsigned p = 0; p < nsub_poly; p++)
9833 error <<
"Subpolyline #("<< p <<
")\n";
9834 poly_to_connect_pt = tmp_vector_subpolylines[p];
9835 const unsigned n_v = poly_to_connect_pt->nvertex();
9836 for (
unsigned i = 0; i < n_v; i++)
9838 Vector<double> cvertex =
9839 poly_to_connect_pt->vertex_coordinate(i);
9841 <<
"Vertex #"<<i<<
": ("<<cvertex[0]<<
", "
9842 <<cvertex[1]<<
")\n";
9845 throw OomphLibError(
9847 "TriangleMesh::create_shared_polylines_connections()",
9848 OOMPH_EXCEPTION_LOCATION);
9856 shd_poly_pt->connect_initial_vertex_to_polyline(
9857 poly_to_connect_pt, vertex_index, sub_poly_to_connect);
9868 unsigned vertex_index = 0;
9870 unsigned sub_poly_to_connect = 0;
9872 bool found_vertex_index =
false;
9876 Vector<unsigned> dst_shd_bnd_ids;
9877 get_shared_boundaries_overlapping_internal_boundary(
9878 uconnection_to_the_left, dst_shd_bnd_ids);
9882 const unsigned n_shd_bnd_overlap_int_bnd =
9883 dst_shd_bnd_ids.size();
9887 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
9890 const unsigned new_connection_to_the_left =
9891 dst_shd_bnd_ids[ss];
9895 if (bound_id != new_connection_to_the_left)
9899 poly_to_connect_pt =
9900 boundary_polyline_pt(new_connection_to_the_left);
9902 if (poly_to_connect_pt != 0)
9906 found_vertex_index =
9907 get_connected_vertex_number_on_destination_polyline(
9908 poly_to_connect_pt, shd_bnd_left_vertex, vertex_index);
9913 if (found_vertex_index)
9925 if (!found_vertex_index)
9929 for (
unsigned isub = 0; isub < nsub_poly; isub++)
9933 if (!boundary_marked_as_shared_boundary(
9934 uconnection_to_the_left, isub))
9937 poly_to_connect_pt = tmp_vector_subpolylines[isub];
9939 found_vertex_index =
9940 get_connected_vertex_number_on_destination_polyline(
9941 poly_to_connect_pt, shd_bnd_left_vertex, vertex_index);
9944 if (found_vertex_index)
9948 sub_poly_to_connect = isub;
9961 if (!found_vertex_index)
9963 std::stringstream error;
9965 <<
"The current shared boundary (" << bound_id <<
") was "
9966 <<
"marked to have a connection\nto the left with the "
9967 <<
"boundary (" << uconnection_to_the_left <<
").\n"
9968 <<
"This last boundary is marked to be overlaped by "
9969 <<
"shared boundaries\n"
9970 <<
"The problem is that the left vertex of the current\n"
9971 <<
"shared boundary is not in the list of vertices of "
9972 <<
"the\nboundary to connect.\n\n"
9973 <<
"This is the left vertex of the current shared "
9975 <<
"Left vertex: (" << shd_bnd_left_vertex[0] <<
", "
9976 << shd_bnd_left_vertex[1] <<
")\n\n"
9977 <<
"This is the list of vertices on the destination "
9978 <<
"boundary (only those subpolylines not marked as "
9979 <<
"overlaped by\nshared boundaries)\n";
9980 for (
unsigned p = 0; p < nsub_poly; p++)
9982 if (!boundary_marked_as_shared_boundary(
9983 uconnection_to_the_left, p))
9985 error <<
"Subpolyline #("<< p <<
")\n";
9986 poly_to_connect_pt = tmp_vector_subpolylines[p];
9987 const unsigned n_v = poly_to_connect_pt->nvertex();
9988 for (
unsigned i = 0; i < n_v; i++)
9990 Vector<double> cvertex =
9991 poly_to_connect_pt->vertex_coordinate(i);
9993 <<
"Vertex #"<<i<<
": ("<<cvertex[0]<<
", "
9994 <<cvertex[1]<<
")\n";
9998 error <<
"\nThis is the list of vertices of the shared "
9999 <<
"polylines that overlap\nthe internal "
10001 Vector<unsigned> dst_shd_bnd_ids;
10002 get_shared_boundaries_overlapping_internal_boundary(
10003 uconnection_to_the_left, dst_shd_bnd_ids);
10004 const unsigned n_shd_bnd_overlap_int_bnd =
10005 dst_shd_bnd_ids.size();
10006 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10008 const unsigned new_connection_to_the_left =
10009 dst_shd_bnd_ids[ss];
10010 poly_to_connect_pt =
10011 boundary_polyline_pt(new_connection_to_the_left);
10012 if (poly_to_connect_pt != 0)
10014 const unsigned shd_bnd_id_overlap =
10015 poly_to_connect_pt->boundary_id();
10016 error <<
"Shared boundary id("
10017 << shd_bnd_id_overlap <<
")\n";
10018 const unsigned n_v = poly_to_connect_pt->nvertex();
10019 for (
unsigned i = 0; i < n_v; i++)
10021 Vector<double> cvertex =
10022 poly_to_connect_pt->vertex_coordinate(i);
10024 <<
"Vertex #"<<i<<
": ("<<cvertex[0]<<
", "
10025 <<cvertex[1]<<
")\n";
10030 throw OomphLibError(
10032 "TriangleMesh::create_shared_polylines_connections()",
10033 OOMPH_EXCEPTION_LOCATION);
10041 shd_poly_pt->connect_initial_vertex_to_polyline(
10042 poly_to_connect_pt, vertex_index, sub_poly_to_connect);
10052 if (is_connected_to_the_right)
10056 const unsigned uconnection_to_the_right =
10057 shd_poly_pt->final_vertex_connected_bnd_id();
10060 TriangleMeshPolyLine *poly_to_connect_pt = 0;
10064 bool connecting_to_an_split_boundary =
false;
10068 bool connecting_to_an_overlaped_boundary =
false;
10071 if (uconnection_to_the_right == bound_id)
10074 poly_to_connect_pt = shd_poly_pt;
10079 const unsigned initial_shd_bnd_id = initial_shared_boundary_id();
10081 if (uconnection_to_the_right >= initial_shd_bnd_id)
10085 poly_to_connect_pt =
10086 boundary_polyline_pt(uconnection_to_the_right);
10094 if (boundary_was_splitted(uconnection_to_the_right))
10096 connecting_to_an_split_boundary =
true;
10106 if (connecting_to_an_split_boundary)
10110 const unsigned n_sub_poly =
10111 nboundary_subpolylines(uconnection_to_the_right);
10116 for (
unsigned ii =0; ii < n_sub_poly; ii++)
10118 if (boundary_marked_as_shared_boundary(
10119 uconnection_to_the_right, ii))
10123 connecting_to_an_overlaped_boundary =
true;
10134 if (boundary_marked_as_shared_boundary(
10135 uconnection_to_the_right, 0))
10139 connecting_to_an_overlaped_boundary =
true;
10146 if (!(connecting_to_an_split_boundary ||
10147 connecting_to_an_overlaped_boundary))
10151 poly_to_connect_pt =
10152 boundary_polyline_pt(uconnection_to_the_right);
10163 if (!connecting_to_an_split_boundary)
10165 if (boundary_was_splitted(uconnection_to_the_right))
10167 std::stringstream error;
10169 <<
"The current shared boundary (" << bound_id <<
") was "
10170 <<
"marked to have a connection\nto the right with the "
10171 <<
"boundary (" << uconnection_to_the_right <<
").\n"
10172 <<
"The problem is that the destination boundary (possibly\n"
10173 <<
"another shared boundary) is marked to be split\n"
10174 <<
"There should not be split shared boundaries\n\n";
10175 throw OomphLibError(
10177 "TriangleMesh::create_shared_polylines_connections()",
10178 OOMPH_EXCEPTION_LOCATION);
10191 Vector<double> shd_bnd_right_vertex =
10192 shd_poly_pt->vertex_coordinate(n_vertex-1);
10196 if (!connecting_to_an_split_boundary)
10200 if (!connecting_to_an_overlaped_boundary)
10205 unsigned vertex_index = 0;
10206 const bool found_vertex_index =
10207 get_connected_vertex_number_on_destination_polyline(
10208 poly_to_connect_pt, shd_bnd_right_vertex, vertex_index);
10212 if (!found_vertex_index)
10214 std::stringstream error;
10216 <<
"The current shared boundary (" << bound_id <<
") was "
10217 <<
"marked to have a connection\nto the right with the "
10218 <<
"boundary (" << uconnection_to_the_right <<
").\n"
10219 <<
"The problem is that the right vertex of the current\n"
10220 <<
"shared boundary is not in the list of vertices of the\n"
10221 <<
"boundary to connect.\n\n"
10222 <<
"This is the right vertex of the current shared boundary\n"
10223 <<
"Right vertex: (" << shd_bnd_right_vertex[0] <<
", "
10224 << shd_bnd_right_vertex[1] <<
")\n\n"
10225 <<
"This is the list of vertices on the destination boundary\n";
10226 const unsigned n_v = poly_to_connect_pt->nvertex();
10227 for (
unsigned i = 0; i < n_v; i++)
10229 Vector<double> cvertex =
10230 poly_to_connect_pt->vertex_coordinate(i);
10232 <<
"Vertex #"<<i<<
": ("<<cvertex[0]<<
", "<<cvertex[1]<<
")\n";
10234 throw OomphLibError(
10236 "TriangleMesh::create_shared_polylines_connections()",
10237 OOMPH_EXCEPTION_LOCATION);
10243 shd_poly_pt->connect_final_vertex_to_polyline(
10244 poly_to_connect_pt, vertex_index);
10254 unsigned vertex_index = 0;
10256 bool found_vertex_index =
false;
10260 Vector<unsigned> dst_shd_bnd_ids;
10261 get_shared_boundaries_overlapping_internal_boundary(
10262 uconnection_to_the_right, dst_shd_bnd_ids);
10266 const unsigned n_shd_bnd_overlap_int_bnd =
10267 dst_shd_bnd_ids.size();
10271 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10274 const unsigned new_connection_to_the_right =
10275 dst_shd_bnd_ids[ss];
10279 poly_to_connect_pt =
10280 boundary_polyline_pt(new_connection_to_the_right);
10282 if (poly_to_connect_pt!=0)
10286 found_vertex_index =
10287 get_connected_vertex_number_on_destination_polyline(
10288 poly_to_connect_pt, shd_bnd_right_vertex, vertex_index);
10293 if (found_vertex_index)
10303 if (!found_vertex_index)
10305 std::stringstream error;
10307 <<
"The current shared boundary (" << bound_id <<
") was "
10308 <<
"marked to have a connection\nto the right with the "
10309 <<
"boundary (" << uconnection_to_the_right <<
").\n"
10310 <<
"This last boundary is marked to be overlaped by "
10311 <<
"shared boundaries\n"
10312 <<
"The problem is that the right vertex of the current\n"
10313 <<
"shared boundary is not in the list of vertices of the\n"
10314 <<
"boundary to connect.\n\n"
10315 <<
"This is the right vertex of the current shared boundary\n"
10316 <<
"Right vertex: (" << shd_bnd_right_vertex[0] <<
", "
10317 << shd_bnd_right_vertex[1] <<
")\n\n"
10318 <<
"This is the list of vertices on the destination "
10320 Vector<unsigned> dst_shd_bnd_ids;
10321 get_shared_boundaries_overlapping_internal_boundary(
10322 uconnection_to_the_right, dst_shd_bnd_ids);
10323 const unsigned n_shd_bnd_overlap_int_bnd =
10324 dst_shd_bnd_ids.size();
10325 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10327 const unsigned new_connection_to_the_right =
10328 dst_shd_bnd_ids[ss];
10329 poly_to_connect_pt =
10330 boundary_polyline_pt(new_connection_to_the_right);
10331 if (poly_to_connect_pt != 0)
10333 const unsigned shd_bnd_id_overlap =
10334 poly_to_connect_pt->boundary_id();
10335 error <<
"Shared boundary id("
10336 << shd_bnd_id_overlap <<
")\n";
10337 const unsigned n_v = poly_to_connect_pt->nvertex();
10338 for (
unsigned i = 0; i < n_v; i++)
10340 Vector<double> cvertex =
10341 poly_to_connect_pt->vertex_coordinate(i);
10343 <<
"Vertex #"<<i<<
": ("<<cvertex[0]<<
", "
10344 <<cvertex[1]<<
")\n";
10349 throw OomphLibError(
10351 "TriangleMesh::create_shared_polylines_connections()",
10352 OOMPH_EXCEPTION_LOCATION);
10360 shd_poly_pt->connect_final_vertex_to_polyline(
10361 poly_to_connect_pt, vertex_index);
10372 Vector<TriangleMeshPolyLine*> tmp_vector_subpolylines =
10373 boundary_subpolylines(uconnection_to_the_right);
10376 const unsigned nsub_poly = tmp_vector_subpolylines.size();
10378 if (nsub_poly <= 1)
10380 std::ostringstream error_message;
10382 <<
"The boundary (" << uconnection_to_the_right <<
") was "
10383 <<
"marked to be splitted but\n"
10384 <<
"there are only ("<<nsub_poly<<
") polylines to "
10385 <<
"represent it.\n";
10386 throw OomphLibError(
10387 error_message.str(),
10388 "TriangleMesh::create_shared_polylines_connections()",
10389 OOMPH_EXCEPTION_LOCATION);
10402 if (!connecting_to_an_overlaped_boundary)
10408 unsigned vertex_index = 0;
10410 unsigned sub_poly_to_connect = 0;
10412 bool found_vertex_index =
false;
10416 for (
unsigned isub = 0; isub < nsub_poly; isub++)
10419 poly_to_connect_pt = tmp_vector_subpolylines[isub];
10421 found_vertex_index =
10422 get_connected_vertex_number_on_destination_polyline(
10423 poly_to_connect_pt, shd_bnd_right_vertex, vertex_index);
10426 if (found_vertex_index)
10430 sub_poly_to_connect = isub;
10438 if (!found_vertex_index)
10440 std::stringstream error;
10442 <<
"The current shared boundary (" << bound_id <<
") was "
10443 <<
"marked to have a connection\nto the right with the "
10444 <<
"boundary (" << uconnection_to_the_right <<
").\n"
10445 <<
"The problem is that the right vertex of the current\n"
10446 <<
"shared boundary is not in the list of vertices of any\n"
10447 <<
"of the sub polylines that represent the boundary to\n"
10449 <<
"This is the right vertex of the current shared boundary\n"
10450 <<
"Right vertex: (" << shd_bnd_right_vertex[0] <<
", "
10451 << shd_bnd_right_vertex[1] <<
")\n\n"
10452 <<
"This is the list of vertices on the destination "
10454 for (
unsigned p = 0; p < nsub_poly; p++)
10456 error <<
"Subpolyline #("<< p <<
")\n";
10457 poly_to_connect_pt = tmp_vector_subpolylines[p];
10458 const unsigned n_v = poly_to_connect_pt->nvertex();
10459 for (
unsigned i = 0; i < n_v; i++)
10461 Vector<double> cvertex =
10462 poly_to_connect_pt->vertex_coordinate(i);
10464 <<
"Vertex #"<<i<<
": ("<<cvertex[0]
10465 <<
", "<<cvertex[1]<<
")\n";
10468 throw OomphLibError(
10470 "TriangleMesh::create_shared_polylines_connections()",
10471 OOMPH_EXCEPTION_LOCATION);
10479 shd_poly_pt->connect_final_vertex_to_polyline(
10480 poly_to_connect_pt, vertex_index, sub_poly_to_connect);
10491 unsigned vertex_index = 0;
10493 unsigned sub_poly_to_connect = 0;
10495 bool found_vertex_index =
false;
10499 Vector<unsigned> dst_shd_bnd_ids;
10500 get_shared_boundaries_overlapping_internal_boundary(
10501 uconnection_to_the_right, dst_shd_bnd_ids);
10505 const unsigned n_shd_bnd_overlap_int_bnd =
10506 dst_shd_bnd_ids.size();
10510 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10513 const unsigned new_connection_to_the_right =
10514 dst_shd_bnd_ids[ss];
10518 if (bound_id != new_connection_to_the_right)
10522 poly_to_connect_pt =
10523 boundary_polyline_pt(new_connection_to_the_right);
10525 if (poly_to_connect_pt != 0)
10529 found_vertex_index =
10530 get_connected_vertex_number_on_destination_polyline(
10531 poly_to_connect_pt, shd_bnd_right_vertex, vertex_index);
10536 if (found_vertex_index)
10548 if (!found_vertex_index)
10552 for (
unsigned isub = 0; isub < nsub_poly; isub++)
10556 if (!boundary_marked_as_shared_boundary(
10557 uconnection_to_the_right, isub))
10560 poly_to_connect_pt = tmp_vector_subpolylines[isub];
10562 found_vertex_index =
10563 get_connected_vertex_number_on_destination_polyline(
10564 poly_to_connect_pt, shd_bnd_right_vertex, vertex_index);
10567 if (found_vertex_index)
10571 sub_poly_to_connect = isub;
10584 if (!found_vertex_index)
10586 std::stringstream error;
10588 <<
"The current shared boundary (" << bound_id <<
") was "
10589 <<
"marked to have a connection\nto the right with the "
10590 <<
"boundary (" << uconnection_to_the_right <<
").\n"
10591 <<
"This last boundary is marked to be overlaped by "
10592 <<
"shared boundaries\n"
10593 <<
"The problem is that the right vertex of the current\n"
10594 <<
"shared boundary is not in the list of vertices of "
10595 <<
"the\nboundary to connect.\n\n"
10596 <<
"This is the right vertex of the current shared "
10598 <<
"Right vertex: (" << shd_bnd_right_vertex[0] <<
", "
10599 << shd_bnd_right_vertex[1] <<
")\n\n"
10600 <<
"This is the list of vertices on the destination "
10601 <<
"boundary (only those subpolylines not marked as "
10602 <<
"overlaped by\nshared boundaries)\n";
10603 for (
unsigned p = 0; p < nsub_poly; p++)
10605 if (!boundary_marked_as_shared_boundary(
10606 uconnection_to_the_right, p))
10608 error <<
"Subpolyline #("<< p <<
")\n";
10609 poly_to_connect_pt = tmp_vector_subpolylines[p];
10610 const unsigned n_v = poly_to_connect_pt->nvertex();
10611 for (
unsigned i = 0; i < n_v; i++)
10613 Vector<double> cvertex =
10614 poly_to_connect_pt->vertex_coordinate(i);
10616 <<
"Vertex #"<<i<<
": ("<<cvertex[0]<<
", "
10617 <<cvertex[1]<<
")\n";
10621 error <<
"\nThis is the list of vertices of the shared "
10622 <<
"polylines that overlap\nthe internal "
10624 Vector<unsigned> dst_shd_bnd_ids;
10625 get_shared_boundaries_overlapping_internal_boundary(
10626 uconnection_to_the_right, dst_shd_bnd_ids);
10627 const unsigned n_shd_bnd_overlap_int_bnd =
10628 dst_shd_bnd_ids.size();
10629 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10631 const unsigned new_connection_to_the_right =
10632 dst_shd_bnd_ids[ss];
10633 poly_to_connect_pt =
10634 boundary_polyline_pt(new_connection_to_the_right);
10635 if (poly_to_connect_pt != 0)
10637 const unsigned shd_bnd_id_overlap =
10638 poly_to_connect_pt->boundary_id();
10639 error <<
"Shared boundary id("
10640 << shd_bnd_id_overlap <<
")\n";
10641 const unsigned n_v = poly_to_connect_pt->nvertex();
10642 for (
unsigned i = 0; i < n_v; i++)
10644 Vector<double> cvertex =
10645 poly_to_connect_pt->vertex_coordinate(i);
10647 <<
"Vertex #"<<i<<
": ("<<cvertex[0]<<
", "
10648 <<cvertex[1]<<
")\n";
10653 throw OomphLibError(
10655 "TriangleMesh::create_shared_polylines_connections()",
10656 OOMPH_EXCEPTION_LOCATION);
10664 shd_poly_pt->connect_final_vertex_to_polyline(
10665 poly_to_connect_pt, vertex_index, sub_poly_to_connect);
10685 template<
class ELEMENT>
10687 Vector<Vector<double> > &output_holes_coordinates)
10690 const unsigned n_proc = this->communicator_pt()->nproc();
10691 const unsigned my_rank = this->communicator_pt()->my_rank();
10695 std::map<FiniteElement*, bool> done_ele;
10699 for (
unsigned iproc = 0; iproc < n_proc; iproc++)
10702 if (iproc != my_rank)
10705 const unsigned n_shd_bnd_iproc = nshared_boundaries(my_rank, iproc);
10710 const unsigned n_shd_bnd_iproc_rev = nshared_boundaries(iproc, my_rank);
10711 if (n_shd_bnd_iproc != n_shd_bnd_iproc_rev)
10713 std::ostringstream error_stream;
10715 <<
"The number of shared boundaries of processor ("
10716 << my_rank <<
") with processor(" << iproc <<
"): ("
10717 << n_shd_bnd_iproc <<
")\n"
10718 <<
"is different from the number of shared boundaries of "
10719 <<
"processor (" << iproc <<
")\nwith processor ("
10720 << my_rank <<
"): (" << n_shd_bnd_iproc <<
")\n\n";
10721 throw OomphLibError(error_stream.str(),
10722 OOMPH_CURRENT_FUNCTION,
10723 OOMPH_EXCEPTION_LOCATION);
10729 for (
unsigned i = 0; i < n_shd_bnd_iproc; i++)
10732 const unsigned shd_bnd_id = shared_boundaries_ids(my_rank, iproc, i);
10735 const unsigned n_shd_bnd_ele = nshared_boundary_element(shd_bnd_id);
10738 for (
unsigned e = 0; e < n_shd_bnd_ele; e++)
10741 FiniteElement* ele_pt = shared_boundary_element_pt(shd_bnd_id, e);
10744 if (ele_pt->is_halo())
10747 if (!done_ele[ele_pt])
10750 const unsigned n_nodes = ele_pt->nnode();
10753 Vector<double> element_centroid(2, 0.0);
10755 for (
unsigned k = 0; k < n_nodes; k++)
10757 Node* tmp_node_pt = ele_pt->node_pt(k);
10759 for (
unsigned d = 0; d < 2; d++)
10761 element_centroid[d]+=tmp_node_pt->x(d);
10766 for (
unsigned d = 0; d < 2; d++)
10768 element_centroid[d] =
10769 element_centroid[d] / (double)n_nodes;
10773 output_holes_coordinates.push_back(element_centroid);
10796 template<
class ELEMENT>
10798 Vector<TriangleMeshPolygon *> &polygons_pt,
10799 Vector<Vector<double> > &output_holes_coordinates)
10817 const unsigned n_input_holes = output_holes_coordinates.size();
10820 if (n_input_holes == 0)
10826 const unsigned n_polygons = polygons_pt.size();
10832 Vector<Vector<Vector<double> > > vertices_polygons(n_polygons);
10835 for (
unsigned p = 0; p < n_polygons; p++)
10838 const unsigned n_polylines = polygons_pt[p]->npolyline();
10840 for (
unsigned pp = 0; pp < n_polylines; pp++)
10843 const TriangleMeshPolyLine* tmp_poly_pt =
10844 polygons_pt[p]->polyline_pt(pp);
10846 const unsigned n_vertices = tmp_poly_pt->nvertex();
10850 for (
unsigned v = 0; v < n_vertices-1; v++)
10853 Vector<double> current_vertex = tmp_poly_pt->vertex_coordinate(v);
10854 vertices_polygons[p].push_back(current_vertex);
10866 std::vector<bool> is_outer_polygon(n_polygons,
true);
10870 if (n_polygons > 1)
10877 Vector<Vector<Vector<double> > > polygon_edge_middle_vertex(n_polygons);
10879 for (
unsigned p = 0; p < n_polygons; p++)
10882 Vector<Vector<double> > tmp_inner_polygon = vertices_polygons[p];
10885 const unsigned n_vertices = tmp_inner_polygon.size();
10888 polygon_edge_middle_vertex[p].resize(n_vertices-1);
10892 for (
unsigned e = 0; e < n_vertices - 1; e++)
10895 const unsigned dim = 2;
10896 polygon_edge_middle_vertex[p][e].resize(dim);
10897 for (
unsigned d = 0; d < dim; d++)
10899 polygon_edge_middle_vertex[p][e][d] =
10900 (tmp_inner_polygon[e][d] + tmp_inner_polygon[e+1][d]) / 2.0;
10909 for (
unsigned idx_inner = 0; idx_inner < n_polygons; idx_inner++)
10914 bool is_inner_polygon =
false;
10919 for (
unsigned i = 0; i < n_polygons; i++)
10922 if (i != idx_inner)
10925 const unsigned n_edges =
10926 polygon_edge_middle_vertex[idx_inner].size();
10929 for (
unsigned e = 0; e < n_edges; e++)
10932 Vector<double> current_vertex =
10933 polygon_edge_middle_vertex[idx_inner][e];
10936 const bool is_point_inside =
10937 is_point_inside_polygon_helper(vertices_polygons[i],
10942 if (is_point_inside)
10945 is_inner_polygon =
true;
10956 if (is_inner_polygon)
10966 if (is_inner_polygon)
10969 is_outer_polygon[idx_inner] =
false;
10975 is_outer_polygon[idx_inner] =
true;
10984 unsigned n_outer_polygons = 0;
10985 unsigned n_inner_polygons = 0;
10987 Vector<unsigned> index_inner_polygon;
10989 for (
unsigned i = 0; i < n_polygons; i++)
10991 if (is_outer_polygon[i])
10994 n_outer_polygons++;
10999 n_inner_polygons++;
11001 index_inner_polygon.push_back(i);
11020 std::vector<bool> is_inside_an_inner_polygon(n_input_holes,
false);
11024 std::vector<bool> is_outside_the_outer_polygons(n_input_holes,
true);
11028 std::vector<bool> is_inside_the_convex_hull(n_input_holes,
false);
11031 Vector<Vector<Vector<double> > >
11032 vertex_inside_inner_polygon(n_inner_polygons);
11037 for (
unsigned i = 0; i < n_inner_polygons; i++)
11040 const unsigned ii = index_inner_polygon[i];
11043 for (
unsigned h = 0; h < n_input_holes; h++)
11047 if (!is_inside_an_inner_polygon[h])
11050 const bool is_inside_polygon =
11051 is_point_inside_polygon_helper(vertices_polygons[ii],
11052 output_holes_coordinates[h]);
11056 if (is_inside_polygon)
11059 is_inside_an_inner_polygon[h] =
true;
11061 vertex_inside_inner_polygon[i].
11062 push_back(output_holes_coordinates[h]);
11074 for (
unsigned h = 0; h < n_input_holes; h++)
11078 if (!is_inside_an_inner_polygon[h])
11082 for (
unsigned i = 0; i < n_polygons; i++)
11085 if (is_outer_polygon[i])
11088 const bool is_inside_polygon =
11089 is_point_inside_polygon_helper(vertices_polygons[i],
11090 output_holes_coordinates[h]);
11095 if (is_inside_polygon)
11098 is_outside_the_outer_polygons[h] =
false;
11112 is_outside_the_outer_polygons[h] =
false;
11119 std::vector<Point> input_vertices_convex_hull;
11122 for (
unsigned p = 0; p < n_polygons; p++)
11125 const unsigned n_vertices = vertices_polygons[p].size();
11127 for (
unsigned v = 0; v < n_vertices; v++)
11132 point.
x = vertices_polygons[p][v][0];
11133 point.
y = vertices_polygons[p][v][1];
11135 input_vertices_convex_hull.push_back(point);
11140 std::vector<Point> output_vertices_convex_hull =
11141 convex_hull(input_vertices_convex_hull);
11144 const unsigned n_vertices_convex_hull = output_vertices_convex_hull.size();
11147 Vector<Vector<double> > vertices_convex_hull(n_vertices_convex_hull);
11148 for (
unsigned i = 0; i < n_vertices_convex_hull; i++)
11151 vertices_convex_hull[i].resize(2);
11153 vertices_convex_hull[i][0] = output_vertices_convex_hull[i].x;
11154 vertices_convex_hull[i][1] = output_vertices_convex_hull[i].y;
11160 for (
unsigned h = 0; h < n_input_holes; h++)
11163 if (is_outside_the_outer_polygons[h])
11166 const bool is_inside_convex_hull =
11167 is_point_inside_polygon_helper(vertices_convex_hull,
11168 output_holes_coordinates[h]);
11171 if (is_inside_convex_hull)
11174 is_inside_the_convex_hull[h] =
true;
11181 is_inside_the_convex_hull[h] =
true;
11188 Vector<Vector<double> > hole_kept;
11189 for (
unsigned h = 0; h < n_input_holes; h++)
11192 if ((is_inside_an_inner_polygon[h]) ||
11193 (is_outside_the_outer_polygons[h] && is_inside_the_convex_hull[h]))
11196 hole_kept.push_back(output_holes_coordinates[h]);
11201 output_holes_coordinates.clear();
11203 output_holes_coordinates = hole_kept;
11211 template<
class ELEMENT>
11214 &unsorted_polylines_pt,
11215 Vector<Vector<TriangleMeshPolyLine *> >
11216 &sorted_polylines_pt)
11218 unsigned n_unsorted_polylines = unsorted_polylines_pt.size();
11219 unsigned n_sorted_polylines = 0;
11220 unsigned curves_index = 0;
11223 std::map<TriangleMeshPolyLine*, bool> done_polyline;
11229 std::list<TriangleMeshPolyLine*> sorted_polyline_list_pt;
11230 bool changes =
false;
11234 TriangleMeshPolyLine* left_pt = 0;
11235 TriangleMeshPolyLine* right_pt = 0;
11239 bool found_root_polyline =
false;
11240 while (pp < n_unsorted_polylines && !found_root_polyline)
11242 if (!done_polyline[unsorted_polylines_pt[pp]])
11243 {found_root_polyline =
true;}
11249 if (pp < n_unsorted_polylines)
11252 left_pt = right_pt = unsorted_polylines_pt[pp];
11253 done_polyline[left_pt] =
true;
11255 n_sorted_polylines++;
11259 sorted_polyline_list_pt.push_back(left_pt);
11265 Vector<double> left_vertex(2);
11266 Vector<double> right_vertex(2);
11268 left_pt->initial_vertex_coordinate(left_vertex);
11269 right_pt->final_vertex_coordinate(right_vertex);
11271 for (
unsigned i = pp+1; i < n_unsorted_polylines; i++)
11273 TriangleMeshPolyLine *current_polyline_pt =
11274 unsorted_polylines_pt[i];
11275 if (!done_polyline[current_polyline_pt])
11277 Vector<double> initial_vertex(2);
11278 Vector<double> final_vertex(2);
11279 current_polyline_pt->initial_vertex_coordinate(initial_vertex);
11280 current_polyline_pt->final_vertex_coordinate(final_vertex);
11286 if (left_vertex == final_vertex)
11288 left_pt = current_polyline_pt;
11289 sorted_polyline_list_pt.push_front(left_pt);
11290 done_polyline[left_pt] =
true;
11291 n_sorted_polylines++;
11297 else if (right_vertex == initial_vertex)
11299 right_pt = current_polyline_pt;
11300 sorted_polyline_list_pt.push_back(right_pt);
11301 done_polyline[right_pt] =
true;
11302 n_sorted_polylines++;
11308 else if (left_vertex == initial_vertex)
11310 current_polyline_pt->reverse();
11311 left_pt = current_polyline_pt;
11312 sorted_polyline_list_pt.push_front(left_pt);
11313 done_polyline[left_pt] =
true;
11314 n_sorted_polylines++;
11320 else if (right_vertex == final_vertex)
11322 current_polyline_pt->reverse();
11323 right_pt = current_polyline_pt;
11324 sorted_polyline_list_pt.push_back(right_pt);
11325 done_polyline[right_pt] =
true;
11326 n_sorted_polylines++;
11332 if (changes) {
break;}
11344 if (!found_root_polyline)
11346 std::stringstream err;
11347 err <<
"It was not possible to find a root polyline to sort the "
11348 <<
"others around it.\nThe number of unsorted and sorted "
11349 <<
"polylines is different, it means that\nnot all the "
11350 <<
"polylines have been sorted.\n"
11351 <<
"Found root polyline: ("<<found_root_polyline<<
")\n"
11352 <<
"Sorted polylines: ("<<n_sorted_polylines<<
")\n"
11353 <<
"Unsorted polylines: ("<<n_unsorted_polylines<<
")\n";
11354 throw OomphLibError(err.str(),
"TriangleMesh::sort_polylines_helper()",
11355 OOMPH_EXCEPTION_LOCATION);
11362 unsigned n_sorted_polyline_on_list = sorted_polyline_list_pt.size();
11365 Vector<TriangleMeshPolyLine *>
11366 tmp_sorted_polylines(n_sorted_polyline_on_list);
11367 unsigned counter = 0;
11369 std::list<TriangleMeshPolyLine*>::iterator it_polyline;
11370 for (it_polyline = sorted_polyline_list_pt.begin();
11371 it_polyline != sorted_polyline_list_pt.end();
11374 tmp_sorted_polylines[counter] = *it_polyline;
11378 sorted_polylines_pt.push_back(tmp_sorted_polylines);
11382 }
while(n_sorted_polylines < n_unsorted_polylines);
11387 if (n_sorted_polylines != n_unsorted_polylines)
11389 std::stringstream err;
11390 err <<
"The number of polylines on the unsorted and sorted vectors"
11391 <<
" is different,\n"
11392 <<
"it means that not all the polylines have been sorted.\n"
11393 <<
"Sorted polylines: "<<n_sorted_polylines
11394 <<
"\nUnsorted polylines: "<<n_unsorted_polylines;
11395 throw OomphLibError(err.str(),
"TriangleMesh::sort_polylines_helper()",
11396 OOMPH_EXCEPTION_LOCATION);
11405 template<
class ELEMENT>
11407 OomphCommunicator* comm_pt,
11408 const Vector<unsigned> &element_domain,
11409 const Vector<GeneralisedElement*> &backed_up_el_pt,
11410 const Vector<FiniteElement*> &backed_up_f_el_pt,
11411 std::map<Data*,std::set<unsigned> > &processors_associated_with_data,
11412 const bool& overrule_keep_as_halo_element_status)
11415 const unsigned nproc = comm_pt->nproc();
11416 const unsigned my_rank = comm_pt->my_rank();
11422 Vector<Vector<Vector<GeneralisedElement*> > > halo_element_pt(nproc);
11424 for (
unsigned iproc = 0; iproc < nproc; iproc++)
11425 {halo_element_pt[iproc].resize(nproc);}
11430 std::map<GeneralisedElement*, unsigned> element_to_global_index;
11433 this->get_halo_elements_on_all_procs(nproc, element_domain,
11435 processors_associated_with_data,
11436 overrule_keep_as_halo_element_status,
11437 element_to_global_index,
11441 flush_shared_boundary_polyline_pt();
11442 Shared_boundary_polyline_pt.resize(nproc);
11448 std::set<FiniteElement*> element_in_processor_pt;
11449 const unsigned n_ele = backed_up_f_el_pt.size();
11450 for (
unsigned e = 0; e < n_ele; e++)
11452 if (element_domain[e] == my_rank)
11454 element_in_processor_pt.insert(backed_up_f_el_pt[e]);
11461 std::map<std::pair<Node*,Node*>,
unsigned> elements_edges_on_boundary;
11462 this->get_element_edges_on_boundary(elements_edges_on_boundary);
11466 this->create_polylines_from_halo_elements_helper(element_domain,
11467 element_to_global_index,
11468 element_in_processor_pt,
11470 elements_edges_on_boundary,
11471 Shared_boundary_polyline_pt);
11480 template<
class ELEMENT>
11482 const unsigned &nproc,
const Vector<unsigned> &element_domain,
11483 const Vector<GeneralisedElement*> &backed_up_el_pt,
11484 std::map<Data*,std::set<unsigned> > &processors_associated_with_data,
11485 const bool&overrule_keep_as_halo_element_status,
11486 std::map<GeneralisedElement*, unsigned> &element_to_global_index,
11487 Vector<Vector<Vector<GeneralisedElement*> > > &output_halo_elements_pt)
11489 const unsigned n_ele = backed_up_el_pt.size();
11492 for (
unsigned iproc = 0; iproc < nproc; iproc++)
11496 Vector<std::map<GeneralisedElement*, bool> > already_added(nproc);
11499 for (
unsigned e=0;e<n_ele;e++)
11502 GeneralisedElement* el_pt=backed_up_el_pt[e];
11503 unsigned el_domain=element_domain[e];
11507 if (el_domain!=iproc)
11512 if ((this->Keep_all_elements_as_halos) ||
11513 (el_pt->must_be_kept_as_halo()))
11515 if (!overrule_keep_as_halo_element_status)
11519 if (!already_added[el_domain][el_pt])
11521 output_halo_elements_pt[iproc][el_domain].push_back(el_pt);
11522 already_added[el_domain][el_pt] =
true;
11523 element_to_global_index[el_pt] = e;
11531 FiniteElement* finite_el_pt =
dynamic_cast<FiniteElement*
>(el_pt);
11532 if(finite_el_pt!=0)
11534 unsigned n_node = finite_el_pt->nnode();
11535 for (
unsigned n=0;n<n_node;n++)
11537 Node* nod_pt=finite_el_pt->node_pt(n);
11540 std::set<unsigned>::iterator it =
11541 processors_associated_with_data[nod_pt].find(iproc);
11542 if (it!=processors_associated_with_data[nod_pt].end())
11546 if (!already_added[el_domain][el_pt])
11548 output_halo_elements_pt[iproc][el_domain].push_back(el_pt);
11549 already_added[el_domain][el_pt] =
true;
11550 element_to_global_index[el_pt] = e;
11569 template <
class ELEMENT>
11571 std::map<std::pair<Node*,Node*>,
unsigned> &element_edges_on_boundary)
11574 const unsigned nbound = this->nboundary();
11576 for (
unsigned b = 0; b < nbound; b++)
11579 std::map<std::pair<Node*, Node*>,
bool> edge_done;
11581 const unsigned nbound_ele = this->nboundary_element(b);
11582 for (
unsigned e = 0; e < nbound_ele; e++)
11585 FiniteElement* bulk_ele_pt = this->boundary_element_pt(b, e);
11587 int face_index = this->face_index_at_boundary(b, e);
11589 FiniteElement* face_ele_pt =
11590 new DummyFaceElement<ELEMENT> (bulk_ele_pt, face_index);
11592 const unsigned nnodes = face_ele_pt->nnode();
11594 Node* first_node_pt = face_ele_pt->node_pt(0);
11595 Node* last_node_pt = face_ele_pt->node_pt(nnodes-1);
11598 std::pair<Node*,Node*> edge =
11599 std::make_pair(first_node_pt, last_node_pt);
11602 if (!edge_done[edge])
11605 edge_done[edge] =
true;
11608 std::pair<Node*,Node*> inv_edge =
11609 std::make_pair(last_node_pt, first_node_pt);
11612 edge_done[inv_edge] =
true;
11615 element_edges_on_boundary[edge] = b;
11619 delete face_ele_pt;
11635 template<
class ELEMENT>
11637 const Vector<unsigned> &element_domain,
11638 std::map<GeneralisedElement*, unsigned> &element_to_global_index,
11639 std::set<FiniteElement*> &element_in_processor_pt,
11640 Vector<Vector<Vector<GeneralisedElement*> > > &input_halo_elements,
11641 std::map<std::pair<Node*,Node*>,
unsigned> &elements_edges_on_boundary,
11642 Vector<Vector<Vector<TriangleMeshPolyLine *> > > &output_polylines_pt)
11644 const unsigned nproc = this->communicator_pt()->nproc();
11645 const unsigned my_rank = this->communicator_pt()->my_rank();
11653 Vector<Vector<Vector<std::pair<Node*,Node*> > > > edges(nproc);
11657 Vector<Vector<Vector<Vector<FiniteElement*> > > > edge_element_pt(nproc);
11662 Vector<Vector<Vector<Vector<int> > > > edge_element_face(nproc);
11667 Vector<Vector<Vector<int> > > edge_boundary(nproc);
11670 std::map<std::pair<Node*,Node*>,
bool> overlapped_edge;
11676 Shared_boundaries_ids.resize(nproc);
11677 for (
unsigned j = 0 ; j < nproc; j++)
11679 edges[j].resize(nproc);
11680 edge_element_pt[j].resize(nproc);
11681 edge_element_face[j].resize(nproc);
11682 edge_boundary[j].resize(nproc);
11685 Shared_boundaries_ids[j].resize(nproc);
11691 for (
unsigned iproc = 0; iproc < nproc; iproc++)
11698 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
11711 Vector<GeneralisedElement*> halo_elements_iproc_with_jproc;
11712 Vector<GeneralisedElement*> halo_elements_jproc_with_iproc;
11715 halo_elements_iproc_with_jproc = input_halo_elements[iproc][jproc];
11718 const unsigned nhalo_elements_iproc_with_jproc =
11719 halo_elements_iproc_with_jproc.size();
11721 if (nhalo_elements_iproc_with_jproc > 0)
11724 halo_elements_jproc_with_iproc = input_halo_elements[jproc][iproc];
11728 const unsigned nhalo_elements_jproc_with_iproc =
11729 halo_elements_jproc_with_iproc.size();
11732 if (nhalo_elements_jproc_with_iproc == 0)
11737 std::stringstream err;
11738 err <<
"There are no halo elements from processor ("<<jproc<<
") "
11739 <<
"with processor ("<<iproc<<
").\n"
11740 <<
"This is strange since there are halo elements from "
11741 <<
"processor ("<<iproc<<
") with processor ("<<jproc<<
").\n"
11742 <<
"Number of halo elements from ("<<iproc<<
") to ("
11743 <<jproc<<
") : ("<< nhalo_elements_iproc_with_jproc<<
")\n"
11744 <<
"Number of halo elements from ("<<jproc<<
") to ("
11745 <<iproc<<
") : ("<< nhalo_elements_jproc_with_iproc<<
")\n";
11746 throw OomphLibError(err.str(),
11747 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11748 OOMPH_EXCEPTION_LOCATION);
11752 Vector<Node*> halo_edges_iproc;
11753 unsigned halo_edges_counter_iproc = 0;
11754 Vector<Node*> halo_edges_jproc;
11755 unsigned halo_edges_counter_jproc = 0;
11758 std::map<std::pair<Node*,Node*>,FiniteElement*> edgesi_to_element_pt;
11762 std::map<std::pair<std::pair<Node*,Node*>, FiniteElement*>,
int>
11763 edgesi_element_pt_to_face_index;
11766 std::map<std::pair<Node*,Node*>,FiniteElement*> edgesj_to_element_pt;
11770 std::map<std::pair<std::pair<Node*,Node*>, FiniteElement*>,
int>
11771 edgesj_element_pt_to_face_index;
11777 for (
unsigned ih = 0; ih < nhalo_elements_iproc_with_jproc; ih++)
11781 element_to_global_index[halo_elements_iproc_with_jproc[ih]];
11783 if (element_domain[e] != jproc)
11786 std::stringstream err;
11787 err <<
"There was a problem on the ihalo-jhalo classification.\n"
11788 <<
"One of the elements, (the one with the ("<<e<<
")-th "
11789 <<
"index ) is not on the ("<<jproc<<
")-th processor\n"
11790 <<
"but it was stored as a halo element of processor ("
11791 << iproc<<
") with processor ("<<jproc<<
").\n";
11792 throw OomphLibError(
11794 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11795 OOMPH_EXCEPTION_LOCATION);
11799 FiniteElement* el_pt =
11800 dynamic_cast<FiniteElement*
>(halo_elements_iproc_with_jproc[ih]);
11804 std::stringstream err;
11805 err <<
"The halo element ("<<ih<<
") could not be casted to the "
11806 <<
"FiniteElement type.\n";
11807 throw OomphLibError(
11809 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11810 OOMPH_EXCEPTION_LOCATION);
11815 const unsigned n_nodes = el_pt->nnode();
11822 std::stringstream err;
11823 err <<
"The number of nodes of the "<<ih<<
"-th halo element is"
11824 <<
" ("<< n_nodes <<
").\nWe can not work with triangle "
11825 <<
"elements with less than three nodes\n";
11826 throw OomphLibError(err.str(),
11827 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11828 OOMPH_EXCEPTION_LOCATION);
11833 Node *first_node_pt = el_pt->node_pt(0);
11834 Node *second_node_pt = el_pt->node_pt(1);
11835 Node *third_node_pt = el_pt->node_pt(2);
11838 halo_edges_iproc.push_back(first_node_pt);
11839 halo_edges_iproc.push_back(second_node_pt);
11840 halo_edges_counter_jproc++;
11842 halo_edges_iproc.push_back(second_node_pt);
11843 halo_edges_iproc.push_back(third_node_pt);
11844 halo_edges_counter_jproc++;
11846 halo_edges_iproc.push_back(third_node_pt);
11847 halo_edges_iproc.push_back(first_node_pt);
11848 halo_edges_counter_jproc++;
11851 std::pair<Node*, Node*> edge1 =
11852 std::make_pair(first_node_pt, second_node_pt);
11853 edgesi_to_element_pt[edge1] = el_pt;
11855 std::pair<Node*, Node*> edge2 =
11856 std::make_pair(second_node_pt, third_node_pt);
11857 edgesi_to_element_pt[edge2] = el_pt;
11859 std::pair<Node*, Node*> edge3 =
11860 std::make_pair(third_node_pt, first_node_pt);
11861 edgesi_to_element_pt[edge3] = el_pt;
11864 std::pair<std::pair<Node*, Node*>, FiniteElement*> edge_ele1 =
11865 std::make_pair(edge1, el_pt);
11866 edgesi_element_pt_to_face_index[edge_ele1] = 2;
11868 std::pair<std::pair<Node*, Node*>, FiniteElement*> edge_ele2 =
11869 std::make_pair(edge2, el_pt);
11870 edgesi_element_pt_to_face_index[edge_ele2] = 0;
11872 std::pair<std::pair<Node*, Node*>, FiniteElement*> edge_ele3 =
11873 std::make_pair(edge3, el_pt);
11874 edgesi_element_pt_to_face_index[edge_ele3] = 1;
11882 for (
unsigned jh = 0; jh < nhalo_elements_jproc_with_iproc; jh++)
11886 element_to_global_index[halo_elements_jproc_with_iproc[jh]];
11888 if (element_domain[e] != iproc)
11891 std::stringstream err;
11892 err <<
"There was a problem on the jhalo-ihalo classification.\n"
11893 <<
"One of the elements, (the one with the ("<<e<<
")-th "
11894 <<
"index ) is not on the ("<<iproc<<
")-th processor\n"
11895 <<
"but it was stored as a halo element of processor ("
11896 << jproc<<
") with processor ("<<iproc<<
").\n";
11897 throw OomphLibError(
11899 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11900 OOMPH_EXCEPTION_LOCATION);
11904 FiniteElement* el_pt =
11905 dynamic_cast<FiniteElement*
>(halo_elements_jproc_with_iproc[jh]);
11908 std::stringstream err;
11909 err <<
"The halo element ("<<jh<<
") could not be casted to the "
11910 <<
"FiniteElement type.\n";
11911 throw OomphLibError(
11913 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11914 OOMPH_EXCEPTION_LOCATION);
11919 const unsigned n_nodes = el_pt->nnode();
11926 std::stringstream err;
11927 err <<
"The number of nodes of the "<<jh<<
"-th halo element is"
11928 <<
" ("<< n_nodes <<
").\nWe can not work with triangle "
11929 <<
"elements with less than three nodes\n";
11930 throw OomphLibError(err.str(),
11931 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11932 OOMPH_EXCEPTION_LOCATION);
11937 Node *first_node_pt = el_pt->node_pt(0);
11938 Node *second_node_pt = el_pt->node_pt(1);
11939 Node *third_node_pt = el_pt->node_pt(2);
11942 halo_edges_jproc.push_back(first_node_pt);
11943 halo_edges_jproc.push_back(second_node_pt);
11944 halo_edges_counter_iproc++;
11946 halo_edges_jproc.push_back(second_node_pt);
11947 halo_edges_jproc.push_back(third_node_pt);
11948 halo_edges_counter_iproc++;
11950 halo_edges_jproc.push_back(third_node_pt);
11951 halo_edges_jproc.push_back(first_node_pt);
11952 halo_edges_counter_iproc++;
11955 std::pair<Node*, Node*> edge1 =
11956 std::make_pair(first_node_pt, second_node_pt);
11957 edgesj_to_element_pt[edge1] = el_pt;
11959 std::pair<Node*, Node*> edge2 =
11960 std::make_pair(second_node_pt, third_node_pt);
11961 edgesj_to_element_pt[edge2] = el_pt;
11963 std::pair<Node*, Node*> edge3 =
11964 std::make_pair(third_node_pt, first_node_pt);
11965 edgesj_to_element_pt[edge3] = el_pt;
11968 std::pair<std::pair<Node*, Node*>, FiniteElement*> edge_ele1 =
11969 std::make_pair(edge1, el_pt);
11970 edgesj_element_pt_to_face_index[edge_ele1] = 2;
11972 std::pair<std::pair<Node*, Node*>, FiniteElement*> edge_ele2 =
11973 std::make_pair(edge2, el_pt);
11974 edgesj_element_pt_to_face_index[edge_ele2] = 0;
11976 std::pair<std::pair<Node*, Node*>, FiniteElement*> edge_ele3 =
11977 std::make_pair(edge3, el_pt);
11978 edgesj_element_pt_to_face_index[edge_ele3] = 1;
11991 unsigned nhalo_iedges = halo_edges_iproc.size();
11992 unsigned nhalo_jedges = halo_edges_jproc.size();
11996 for (
unsigned ihe = 0; ihe < nhalo_iedges; ihe+=2)
11999 Vector<Node*> ihalo_edge(2);
12000 ihalo_edge[0] = halo_edges_iproc[ihe];
12001 ihalo_edge[1] = halo_edges_iproc[ihe+1];
12004 std::pair<Node*,Node*> tmp_edge = std::make_pair(ihalo_edge[0],
12009 int edge_boundary_id = -1;
12011 std::map<std::pair<Node*,Node*>,
unsigned >::iterator it;
12012 it = elements_edges_on_boundary.find(tmp_edge);
12015 if (it != elements_edges_on_boundary.end())
12019 edge_boundary_id = (*it).second;
12025 std::pair<Node*,Node*> rtmp_edge = std::make_pair(ihalo_edge[1],
12027 it = elements_edges_on_boundary.find(rtmp_edge);
12028 if (it != elements_edges_on_boundary.end())
12032 edge_boundary_id = (*it).second;
12039 for (
unsigned jhe = 0; jhe < nhalo_jedges; jhe+=2)
12042 Vector<Node*> jhalo_edge(2);
12043 jhalo_edge[0] = halo_edges_jproc[jhe];
12044 jhalo_edge[1] = halo_edges_jproc[jhe+1];
12047 if (ihalo_edge[0] == jhalo_edge[0] &&
12048 ihalo_edge[1] == jhalo_edge[1])
12051 std::pair<Node*, Node*> new_edge =
12052 std::make_pair(ihalo_edge[0], ihalo_edge[1]);
12057 FiniteElement* haloi_ele_pt = 0;
12058 haloi_ele_pt = edgesi_to_element_pt[new_edge];
12059 FiniteElement* haloj_ele_pt = 0;
12060 haloj_ele_pt = edgesj_to_element_pt[new_edge];
12063 if (haloi_ele_pt == 0 || haloj_ele_pt == 0)
12065 std::stringstream err;
12066 err <<
"There is no associated elements with the new "
12067 <<
"shared boundary. This is an storing problem,\n"
12068 <<
"possibly related with a memory leak problem!!!\n"
12069 <<
"The nodes that compound the edge are these:\n"
12070 <<
"On processor ("<<iproc<<
"):\n"
12071 <<
"("<<ihalo_edge[0]->x(0)<<
", "<<ihalo_edge[0]->x(1)
12072 <<
") and ("<<ihalo_edge[1]->x(0)<<
", "
12073 <<ihalo_edge[1]->x(1)<<
")\n\n"
12074 <<
"On processor ("<<jproc<<
"):\n"
12075 <<
"("<<jhalo_edge[0]->x(0)<<
", "<<jhalo_edge[0]->x(1)
12076 <<
") and ("<<jhalo_edge[1]->x(0)<<
", "
12077 <<jhalo_edge[1]->x(1)<<
")\n\n"
12078 <<
"The nodes coordinates should be the same!!!\n";
12079 throw OomphLibError(err.str(),
12080 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12081 OOMPH_EXCEPTION_LOCATION);
12085 edges[iproc][jproc].push_back(new_edge);
12088 if (edge_boundary_id >= 0)
12091 overlapped_edge[new_edge] =
true;
12094 std::pair<Node*, Node*> rev_new_edge =
12095 std::make_pair(ihalo_edge[1], ihalo_edge[0]);
12098 overlapped_edge[rev_new_edge] =
true;
12104 edge_boundary[iproc][jproc].push_back(edge_boundary_id);
12107 Vector<FiniteElement*> tmp_elements_pt;
12108 tmp_elements_pt.push_back(haloi_ele_pt);
12109 tmp_elements_pt.push_back(haloj_ele_pt);
12112 edge_element_pt[iproc][jproc].push_back(tmp_elements_pt);
12118 std::pair<std::pair<Node*,Node*>, FiniteElement*>
12119 edge_elementi_pair = make_pair(new_edge, haloi_ele_pt);
12121 std::pair<std::pair<Node*,Node*>, FiniteElement*>
12122 edge_elementj_pair = make_pair(new_edge, haloj_ele_pt);
12126 int face_index_haloi_ele = -1;
12127 face_index_haloi_ele =
12128 edgesi_element_pt_to_face_index[edge_elementi_pair];
12129 int face_index_haloj_ele = -1;
12130 face_index_haloj_ele =
12131 edgesj_element_pt_to_face_index[edge_elementj_pair];
12133 if (face_index_haloi_ele == -1 || face_index_haloj_ele == -1)
12135 std::stringstream err;
12136 err <<
"There is no associated face indexes to the"
12137 <<
"elements that gave\nrise to the shared edge\n"
12138 <<
"The nodes that compound the edge are these:\n"
12139 <<
"On processor ("<<iproc<<
"):\n"
12140 <<
"("<<ihalo_edge[0]->x(0)<<
", "<<ihalo_edge[0]->x(1)
12141 <<
") and ("<<ihalo_edge[1]->x(0)<<
", "
12142 <<ihalo_edge[1]->x(1)<<
")\n\n"
12143 <<
"On processor ("<<jproc<<
"):\n"
12144 <<
"("<<jhalo_edge[0]->x(0)<<
", "<<jhalo_edge[0]->x(1)
12145 <<
") and ("<<jhalo_edge[1]->x(0)<<
", "
12146 <<jhalo_edge[1]->x(1)<<
")\n\n"
12147 <<
"The nodes coordinates should be the same!!!\n";
12148 throw OomphLibError(err.str(),
12149 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12150 OOMPH_EXCEPTION_LOCATION);
12155 Vector<int> tmp_edge_element_face_index;
12156 tmp_edge_element_face_index.push_back(face_index_haloi_ele);
12157 tmp_edge_element_face_index.push_back(face_index_haloj_ele);
12159 edge_element_face[iproc][jproc].
12160 push_back(tmp_edge_element_face_index);
12168 else if (ihalo_edge[0] == jhalo_edge[1] &&
12169 ihalo_edge[1] == jhalo_edge[0])
12172 std::pair<Node*, Node*> new_edge =
12173 std::make_pair(ihalo_edge[0], ihalo_edge[1]);
12177 FiniteElement* haloi_ele_pt = 0;
12178 haloi_ele_pt = edgesi_to_element_pt[new_edge];
12180 FiniteElement* haloj_ele_pt = 0;
12183 std::pair<Node*, Node*> new_edge_reversed =
12184 std::make_pair(jhalo_edge[0], jhalo_edge[1]);
12185 haloj_ele_pt = edgesj_to_element_pt[new_edge_reversed];
12188 if (haloi_ele_pt == 0 || haloj_ele_pt == 0)
12190 std::stringstream err;
12191 err <<
"There is no associated elements with the new "
12192 <<
"shared boundary (reversed version). This is an "
12193 <<
"storing problem, possibly related with a memory "
12194 <<
"leak problem!!!\n"
12195 <<
"The nodes that compound the edge are these:\n"
12196 <<
"On processor ("<<iproc<<
"):\n"
12197 <<
"("<<ihalo_edge[0]->x(0)<<
", "<<ihalo_edge[0]->x(1)
12198 <<
") and ("<<ihalo_edge[1]->x(0)<<
", "
12199 <<ihalo_edge[1]->x(1)<<
")\n\n"
12200 <<
"On processor ("<<jproc<<
"):\n"
12201 <<
"("<<jhalo_edge[0]->x(0)<<
", "<<jhalo_edge[0]->x(1)
12202 <<
") and ("<<jhalo_edge[1]->x(0)<<
", "
12203 <<jhalo_edge[1]->x(1)<<
")\n\n"
12204 <<
"The nodes coordinates should be the same!!!\n";
12205 throw OomphLibError(err.str(),
12206 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12207 OOMPH_EXCEPTION_LOCATION);
12211 edges[iproc][jproc].push_back(new_edge);
12214 if (edge_boundary_id >= 0)
12217 overlapped_edge[new_edge] =
true;
12220 std::pair<Node*, Node*> rev_new_edge =
12221 std::make_pair(ihalo_edge[1], ihalo_edge[0]);
12224 overlapped_edge[rev_new_edge] =
true;
12229 edge_boundary[iproc][jproc].push_back(edge_boundary_id);
12232 Vector<FiniteElement*> tmp_elements_pt;
12233 tmp_elements_pt.push_back(haloi_ele_pt);
12234 tmp_elements_pt.push_back(haloj_ele_pt);
12237 edge_element_pt[iproc][jproc].push_back(tmp_elements_pt);
12243 std::pair<std::pair<Node*,Node*>, FiniteElement*>
12244 edge_elementi_pair = make_pair(new_edge, haloi_ele_pt);
12246 std::pair<std::pair<Node*,Node*>, FiniteElement*>
12247 edge_elementj_pair = make_pair(new_edge_reversed,
12252 int face_index_haloi_ele = -1;
12253 face_index_haloi_ele =
12254 edgesi_element_pt_to_face_index[edge_elementi_pair];
12255 int face_index_haloj_ele = -1;
12256 face_index_haloj_ele =
12257 edgesj_element_pt_to_face_index[edge_elementj_pair];
12259 if (face_index_haloi_ele == -1 || face_index_haloj_ele == -1)
12261 std::stringstream err;
12262 err <<
"There is no associated face indexes to the"
12263 <<
"elements that gave\nrise to the shared edge\n"
12264 <<
"The nodes that compound the edge are these:\n"
12265 <<
"On processor ("<<iproc<<
"):\n"
12266 <<
"("<<ihalo_edge[0]->x(0)<<
", "<<ihalo_edge[0]->x(1)
12267 <<
") and ("<<ihalo_edge[1]->x(0)<<
", "
12268 <<ihalo_edge[1]->x(1)<<
")\n\n"
12269 <<
"On processor ("<<jproc<<
"):\n"
12270 <<
"("<<jhalo_edge[0]->x(0)<<
", "<<jhalo_edge[0]->x(1)
12271 <<
") and ("<<jhalo_edge[1]->x(0)<<
", "
12272 <<jhalo_edge[1]->x(1)<<
")\n\n"
12273 <<
"The nodes coordinates should be the same!!!\n";
12274 throw OomphLibError(err.str(),
12275 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12276 OOMPH_EXCEPTION_LOCATION);
12281 Vector<int> tmp_edge_element_face_index;
12282 tmp_edge_element_face_index.push_back(face_index_haloi_ele);
12283 tmp_edge_element_face_index.push_back(face_index_haloj_ele);
12285 edge_element_face[iproc][jproc].
12286 push_back(tmp_edge_element_face_index);
12311 std::map<Node*, unsigned> global_shared_node_degree;
12315 std::map<std::pair<Node*, Node*>,
bool> edge_done;
12316 #endif // #ifdef PARANOID
12318 std::map<Node*,bool> node_done;
12322 for (
unsigned iproc = 0; iproc < nproc; iproc++)
12329 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
12332 const unsigned nshd_edges = edges[iproc][jproc].size();
12338 const unsigned nedge_element = edge_element_pt[iproc][jproc].size();
12339 if (nshd_edges != nedge_element)
12341 std::stringstream error_message;
12343 <<
"The number of shared edges between processor iproc and jproc\n"
12344 <<
"is different form the number of edge elements between the\n"
12345 <<
"pair of processors\n"
12346 <<
"iproc: (" << iproc <<
")\n"
12347 <<
"jproc: (" << jproc <<
")\n"
12348 <<
"# of shared edges: (" << nshd_edges <<
")\n"
12349 <<
"# of edge elements: (" << nedge_element <<
")\n\n";
12350 throw OomphLibError(error_message.str(),
12351 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12352 OOMPH_EXCEPTION_LOCATION);
12356 const unsigned nedge_element_face =
12357 edge_element_face[iproc][jproc].size();
12358 if (nshd_edges != nedge_element_face)
12360 std::stringstream error_message;
12362 <<
"The number of shared edges between processor iproc and jproc\n"
12363 <<
"is different form the number of edge element faces between the\n"
12364 <<
"pair of processors\n"
12365 <<
"iproc: (" << iproc <<
")\n"
12366 <<
"jproc: (" << jproc <<
")\n"
12367 <<
"# of shared edges: (" << nshd_edges <<
")\n"
12368 <<
"# of edge element faces: (" << nedge_element_face <<
")\n\n";
12369 throw OomphLibError(error_message.str(),
12370 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12371 OOMPH_EXCEPTION_LOCATION);
12375 const unsigned nedge_boundary = edge_boundary[iproc][jproc].size();
12376 if (nshd_edges != nedge_boundary)
12378 std::stringstream error_message;
12380 <<
"The number of shared edges between processor iproc and jproc\n"
12381 <<
"is different form the number of edge boundaries ids between the\n"
12382 <<
"pair of processors\n"
12383 <<
"iproc: (" << iproc <<
")\n"
12384 <<
"jproc: (" << jproc <<
")\n"
12385 <<
"# of shared edges: (" << nshd_edges <<
")\n"
12386 <<
"# of edge boundaries ids: (" << nedge_boundary <<
")\n\n";
12387 throw OomphLibError(error_message.str(),
12388 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12389 OOMPH_EXCEPTION_LOCATION);
12392 #endif // #ifdef PARANOID
12395 for (
unsigned se = 0; se < nshd_edges; se++)
12398 std::pair<Node*, Node*> edge = edges[iproc][jproc][se];
12401 if (edge_done[edge])
12403 std::stringstream error_message;
12405 <<
"The shared edge between processor iproc and processor\n"
12406 <<
"jproc has been already visited, this is weird since the\n"
12407 <<
"edge should not be shared by other pair of processors\n"
12408 <<
"iproc: (" << iproc <<
")\n"
12409 <<
"jproc: (" << jproc <<
")\n"
12410 <<
"First node of edge: (" << edge.first->x(0) <<
", "
12411 << edge.first->x(1) <<
")\n"
12412 <<
"Second node of edge: (" << edge.second->x(0) <<
", "
12413 << edge.second->x(1) <<
")\n"
12414 <<
"Associated edge boundary id: ("
12415 << edge_boundary[iproc][jproc][se] <<
")\n\n";
12416 throw OomphLibError(error_message.str(),
12417 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12418 OOMPH_EXCEPTION_LOCATION);
12422 edge_done[edge] =
true;
12424 std::pair<Node*, Node*> rev_edge =
12425 std::make_pair(edge.second, edge.first);
12427 edge_done[rev_edge] =
true;
12428 #endif // #ifdef PARANOID
12431 Node* left_node_pt = edge.first;
12432 Node* right_node_pt = edge.second;
12435 if (!node_done[left_node_pt])
12439 global_shared_node_degree[left_node_pt] = 1;
12445 global_shared_node_degree[left_node_pt]++;
12449 if (!node_done[right_node_pt])
12453 global_shared_node_degree[right_node_pt] = 1;
12458 global_shared_node_degree[right_node_pt]++;
12473 std::map<unsigned, std::map<Node*, bool> >
12474 node_on_bnd_not_overlapped_by_shd_bnd;
12477 for (std::map<std::pair<Node*,Node*>,
unsigned>::iterator it_map =
12478 elements_edges_on_boundary.begin();
12479 it_map != elements_edges_on_boundary.end(); it_map++)
12482 std::pair<Node*,Node*> edge_pair = (*it_map).first;
12485 if (!overlapped_edge[edge_pair])
12489 unsigned b = (*it_map).second;
12492 Node* left_node_pt = edge_pair.first;
12493 node_on_bnd_not_overlapped_by_shd_bnd[b][left_node_pt] =
true;
12496 Node* right_node_pt = edge_pair.second;
12497 node_on_bnd_not_overlapped_by_shd_bnd[b][right_node_pt] =
true;
12512 Vector<Vector<TriangleMeshPolyLine *> > unsorted_polylines_pt(nproc);
12517 std::map<unsigned, std::list<Node*> > shared_bnd_id_to_sorted_list_node_pt;
12521 unsigned shared_boundary_id_start = this->nboundary();
12522 Initial_shared_boundary_id = shared_boundary_id_start;
12528 for (
unsigned iproc = 0; iproc < nproc; iproc++)
12535 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
12543 unsigned npolylines_counter = 0;
12544 const unsigned nedges = edges[iproc][jproc].size();
12550 unsigned nsorted_edges = 0;
12553 std::map<std::pair<Node*,Node*>,
bool> edge_done;
12557 while(nsorted_edges < nedges)
12561 std::list<FiniteElement*> tmp_boundary_element_pt;
12564 std::list<int> tmp_face_index_element;
12566 std::pair<Node*,Node*> edge;
12568 bool found_initial_edge =
false;
12570 int root_edge_bound_id = -1;
12571 unsigned iedge = 0;
12572 for (iedge = 0; iedge < nedges; iedge++)
12574 edge = edges[iproc][jproc][iedge];
12576 if (!edge_done[edge])
12579 root_edge_bound_id = edge_boundary[iproc][jproc][iedge];
12581 found_initial_edge =
true;
12590 if (!found_initial_edge)
12592 std::ostringstream error_message;
12594 <<
"All the edge are already done, but the number of done\n"
12595 <<
"edges ("<<nsorted_edges<<
") is still less than the total\n"
12596 <<
"number of edges (" << nedges <<
").\n";
12598 throw OomphLibError(error_message.str(),
12599 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12600 OOMPH_EXCEPTION_LOCATION);
12606 std::list<Node*> sorted_nodes;
12607 sorted_nodes.clear();
12610 Node *first_node_pt = edge.first;
12611 Node *last_node_pt = edge.second;
12614 sorted_nodes.push_back(first_node_pt);
12615 sorted_nodes.push_back(last_node_pt);
12619 tmp_boundary_element_pt.
12620 push_back(edge_element_pt[iproc][jproc][iedge-1][0]);
12621 tmp_boundary_element_pt.
12622 push_back(edge_element_pt[iproc][jproc][iedge-1][1]);
12626 tmp_face_index_element.
12627 push_back(edge_element_face[iproc][jproc][iedge-1][0]);
12628 tmp_face_index_element.
12629 push_back(edge_element_face[iproc][jproc][iedge-1][1]);
12632 edge_done[edge] =
true;
12637 bool node_added =
true;
12641 bool node_added_to_the_left =
true;
12642 bool node_added_to_the_right =
true;
12660 bool connection_to_the_left =
false;
12665 bool connection_to_the_right =
false;
12669 bool current_polyline_has_connections_at_both_ends =
false;
12676 int bound_id_connection_to_the_left = -1;
12677 int bound_id_connection_to_the_right = -1;
12680 const unsigned first_node_degree =
12681 global_shared_node_degree[first_node_pt];
12685 bound_id_connection_to_the_left =
12686 check_connections_of_polyline_nodes(
12687 element_in_processor_pt,
12688 root_edge_bound_id,
12690 node_on_bnd_not_overlapped_by_shd_bnd,
12692 shared_bnd_id_to_sorted_list_node_pt,
12702 if (bound_id_connection_to_the_left != -1)
12704 connection_to_the_left =
true;
12708 const unsigned last_node_degree =
12709 global_shared_node_degree[last_node_pt];
12713 bound_id_connection_to_the_right =
12714 check_connections_of_polyline_nodes(
12715 element_in_processor_pt,
12716 root_edge_bound_id,
12718 node_on_bnd_not_overlapped_by_shd_bnd,
12720 shared_bnd_id_to_sorted_list_node_pt,
12729 if (bound_id_connection_to_the_right != -1)
12731 connection_to_the_right =
true;
12736 if (connection_to_the_left && connection_to_the_right)
12737 {current_polyline_has_connections_at_both_ends =
true;}
12744 while(node_added && (nsorted_edges < nedges)
12745 && !current_polyline_has_connections_at_both_ends)
12750 for (
unsigned iiedge = iedge; iiedge < nedges; iiedge++)
12753 node_added =
false;
12754 node_added_to_the_left =
false;
12755 node_added_to_the_right =
false;
12757 edge = edges[iproc][jproc][iiedge];
12758 const int edge_bound_id = edge_boundary[iproc][jproc][iiedge];
12764 if (!edge_done[edge] &&
12765 (edge_bound_id == root_edge_bound_id))
12768 Node* left_node_pt = edge.first;
12769 Node* right_node_pt = edge.second;
12772 Node* new_added_node_pt = 0;
12775 if (left_node_pt == first_node_pt &&
12776 !connection_to_the_left)
12779 sorted_nodes.push_front(right_node_pt);
12781 new_added_node_pt = first_node_pt = right_node_pt;
12785 node_added_to_the_left =
true;
12788 else if (left_node_pt == last_node_pt &&
12789 !connection_to_the_right)
12792 sorted_nodes.push_back(right_node_pt);
12794 new_added_node_pt = last_node_pt = right_node_pt;
12798 node_added_to_the_right =
true;
12801 else if (right_node_pt == first_node_pt &&
12802 !connection_to_the_left)
12805 sorted_nodes.push_front(left_node_pt);
12807 new_added_node_pt = first_node_pt = left_node_pt;
12811 node_added_to_the_left =
true;
12814 else if (right_node_pt == last_node_pt &&
12815 !connection_to_the_right)
12818 sorted_nodes.push_back(left_node_pt);
12820 new_added_node_pt = last_node_pt = left_node_pt;
12824 node_added_to_the_right =
true;
12834 edge_done[edge] =
true;
12838 const unsigned added_node_degree =
12839 global_shared_node_degree[new_added_node_pt];
12841 if (node_added_to_the_left)
12844 tmp_boundary_element_pt.push_front(
12845 edge_element_pt[iproc][jproc][iiedge][1]);
12846 tmp_boundary_element_pt.push_front(
12847 edge_element_pt[iproc][jproc][iiedge][0]);
12849 tmp_face_index_element.push_front(
12850 edge_element_face[iproc][jproc][iiedge][1]);
12851 tmp_face_index_element.push_front(
12852 edge_element_face[iproc][jproc][iiedge][0]);
12855 if (node_added_to_the_right)
12858 tmp_boundary_element_pt.push_back(
12859 edge_element_pt[iproc][jproc][iiedge][0]);
12860 tmp_boundary_element_pt.push_back(
12861 edge_element_pt[iproc][jproc][iiedge][1]);
12863 tmp_face_index_element.push_back(
12864 edge_element_face[iproc][jproc][iiedge][0]);
12865 tmp_face_index_element.push_back(
12866 edge_element_face[iproc][jproc][iiedge][1]);
12876 if (node_added_to_the_left && !connection_to_the_left)
12879 bound_id_connection_to_the_left =
12880 check_connections_of_polyline_nodes(
12881 element_in_processor_pt,
12882 root_edge_bound_id,
12884 node_on_bnd_not_overlapped_by_shd_bnd,
12886 shared_bnd_id_to_sorted_list_node_pt,
12888 new_added_node_pt);
12895 if (bound_id_connection_to_the_left != -1)
12897 connection_to_the_left =
true;
12907 if (node_added_to_the_right && !connection_to_the_right)
12910 bound_id_connection_to_the_right =
12911 check_connections_of_polyline_nodes(
12912 element_in_processor_pt,
12913 root_edge_bound_id,
12915 node_on_bnd_not_overlapped_by_shd_bnd,
12917 shared_bnd_id_to_sorted_list_node_pt,
12919 new_added_node_pt);
12926 if (bound_id_connection_to_the_right != -1)
12928 connection_to_the_right =
true;
12936 if (connection_to_the_left && connection_to_the_right)
12937 {current_polyline_has_connections_at_both_ends =
true;}
12960 const unsigned n_bnd_ele = tmp_boundary_element_pt.size();
12963 Vector<FiniteElement*> tmp_bnd_ele_pt(n_bnd_ele);
12964 Vector<int> tmp_face_idx_ele(n_bnd_ele);
12966 unsigned help_counter = 0;
12968 for (std::list<FiniteElement*>::iterator it_bnd_ele =
12969 tmp_boundary_element_pt.begin();
12970 it_bnd_ele != tmp_boundary_element_pt.end();
12973 tmp_bnd_ele_pt[help_counter++] = (*it_bnd_ele);
12978 for (std::list<int>::iterator it_face_idx =
12979 tmp_face_index_element.begin();
12980 it_face_idx != tmp_face_index_element.end();
12983 tmp_face_idx_ele[help_counter++] = (*it_face_idx);
12988 Vector<std::list<Node*> > final_sorted_nodes_pt;
12991 Vector<Vector<FiniteElement*> > final_boundary_element_pt;
12993 Vector<Vector<int> > final_face_index_element;
12996 Vector<int> final_bound_id_connection_to_the_left;
12999 Vector<int> final_bound_id_connection_to_the_right;
13002 break_loops_on_shared_polyline_helper(
13003 shared_boundary_id_start,
13005 tmp_bnd_ele_pt, tmp_face_idx_ele,
13006 bound_id_connection_to_the_left, bound_id_connection_to_the_right,
13007 final_sorted_nodes_pt,
13008 final_boundary_element_pt, final_face_index_element,
13009 final_bound_id_connection_to_the_left,
13010 final_bound_id_connection_to_the_right);
13013 const unsigned n_final_sorted_nodes =
13014 final_sorted_nodes_pt.size();
13017 for (
unsigned i = 0; i < n_final_sorted_nodes; i++)
13022 shared_bnd_id_to_sorted_list_node_pt[shared_boundary_id_start] =
13023 final_sorted_nodes_pt[i];
13027 create_shared_polyline(my_rank, shared_boundary_id_start,
13028 iproc, jproc, final_sorted_nodes_pt[i],
13029 root_edge_bound_id,
13030 final_boundary_element_pt[i],
13031 final_face_index_element[i],
13032 unsorted_polylines_pt,
13033 final_bound_id_connection_to_the_left[i],
13034 final_bound_id_connection_to_the_right[i]);
13038 npolylines_counter++;
13042 shared_boundary_id_start++;
13055 if (unsorted_polylines_pt[iproc].size() > 0)
13059 sort_polylines_helper(unsorted_polylines_pt[iproc],
13060 output_polylines_pt[iproc]);
13064 const unsigned nunsorted_polylines_iproc =
13065 unsorted_polylines_pt[iproc].size();
13068 unsigned tmp_ntotal_polylines = 0;
13070 for (
unsigned ii = 0 ; ii < output_polylines_pt[iproc].size(); ii++)
13071 {tmp_ntotal_polylines+= output_polylines_pt[iproc][ii].size();}
13072 if (tmp_ntotal_polylines != nunsorted_polylines_iproc)
13074 std::ostringstream error_message;
13076 <<
" The total number of unsorted polylines ("
13077 << nunsorted_polylines_iproc <<
") in common with\nprocessor ("
13078 << iproc<<
") is different from the total number of sorted "
13079 <<
"polylines (" << tmp_ntotal_polylines <<
") with\nthe same "
13081 throw OomphLibError(error_message.str(),
13082 OOMPH_CURRENT_FUNCTION,
13083 OOMPH_EXCEPTION_LOCATION);
13090 this->Final_shared_boundary_id = shared_boundary_id_start;
13098 template<
class ELEMENT>
13100 const unsigned &initial_shd_bnd_id,
13101 std::list<Node*> &input_nodes,
13102 Vector<FiniteElement*> &input_boundary_element_pt,
13103 Vector<int> &input_face_index_element,
13104 const int &input_connect_to_the_left,
13105 const int &input_connect_to_the_right,
13106 Vector<std::list<Node*> > &output_sorted_nodes_pt,
13107 Vector<Vector<FiniteElement*> > &output_boundary_element_pt,
13108 Vector<Vector<int> > &output_face_index_element,
13109 Vector<int> &output_connect_to_the_left,
13110 Vector<int> &output_connect_to_the_right)
13113 Node* left_node_pt = input_nodes.front();
13114 Node* right_node_pt = input_nodes.back();
13118 Vector<std::list<Node*> > tmp_sub_nodes;
13119 Vector<Vector<FiniteElement*> > tmp_sub_bnd_ele_pt;
13120 Vector<Vector<int> > tmp_sub_face_idx_ele;
13123 std::list<Node*>::iterator it = input_nodes.begin();
13126 unsigned counter = 0;
13129 while(it != input_nodes.end())
13134 if (it == input_nodes.end())
13146 std::list<Node*> sub_nodes;
13149 Vector<FiniteElement*> sub_bnd_ele_pt;
13152 Vector<int> sub_face_idx_ele;
13155 sub_nodes.push_back(*it);
13165 sub_nodes.push_back((*it));
13168 sub_bnd_ele_pt.push_back(input_boundary_element_pt[counter]);
13169 sub_bnd_ele_pt.push_back(input_boundary_element_pt[counter+1]);
13172 sub_face_idx_ele.push_back(input_face_index_element[counter]);
13173 sub_face_idx_ele.push_back(input_face_index_element[counter+1]);
13180 }
while((*it) != left_node_pt &&
13181 (*it) != right_node_pt &&
13182 it != input_nodes.end());
13185 tmp_sub_nodes.push_back(sub_nodes);
13187 tmp_sub_bnd_ele_pt.push_back(sub_bnd_ele_pt);
13189 tmp_sub_face_idx_ele.push_back(sub_face_idx_ele);
13197 const unsigned n_sub_list = tmp_sub_nodes.size();
13200 if (n_sub_list > 3)
13202 std::stringstream error_message;
13204 <<
"The number of sub-list of nodes created from the shared\n"
13205 <<
"polyline with loops was (" << n_sub_list <<
").\n"
13206 <<
"We can only handle up to three sub-list of nodes\n";
13207 throw OomphLibError(error_message.str(),
13208 OOMPH_CURRENT_FUNCTION,
13209 OOMPH_EXCEPTION_LOCATION);
13215 if (n_sub_list == 1 && (left_node_pt != right_node_pt))
13223 output_sorted_nodes_pt = tmp_sub_nodes;
13225 output_boundary_element_pt = tmp_sub_bnd_ele_pt;
13227 output_face_index_element = tmp_sub_face_idx_ele;
13233 if (input_connect_to_the_left == -2)
13235 std::stringstream error_message;
13237 <<
"The connection flag to the left ("
13238 << input_connect_to_the_left <<
") indicates a connection\n"
13239 <<
"with the same polyline.\n However, only one sub-polyline was "
13240 <<
"found and no loop\nwas identified\n\n";
13241 throw OomphLibError(error_message.str(),
13242 OOMPH_CURRENT_FUNCTION,
13243 OOMPH_EXCEPTION_LOCATION);
13248 if (input_connect_to_the_left == -3)
13250 output_connect_to_the_left.push_back(-1);
13254 output_connect_to_the_left.push_back(input_connect_to_the_left);
13258 if (input_connect_to_the_right == -2)
13260 std::stringstream error_message;
13262 <<
"The connection flag to the right ("
13263 << input_connect_to_the_right <<
") indicates a connection\n"
13264 <<
"with the same polyline.\n However, only one sub-polyline was "
13265 <<
"found and no loop\nwas identified\n\n";
13266 throw OomphLibError(error_message.str(),
13267 "TriangleMesh::break_loops_on_shared_polyline_helper()",
13268 OOMPH_EXCEPTION_LOCATION);
13273 if (input_connect_to_the_right == -3)
13275 output_connect_to_the_right.push_back(-1);
13279 output_connect_to_the_right.push_back(input_connect_to_the_right);
13287 unsigned tmp_shd_bnd_id = initial_shd_bnd_id;
13295 Node* left_sub_node_pt = tmp_sub_nodes[0].front();
13296 Node* right_sub_node_pt = tmp_sub_nodes[0].back();
13299 if (left_sub_node_pt == right_sub_node_pt)
13305 std::list<Node*> first_half_node_pt;
13306 std::list<Node*> second_half_node_pt;
13308 Vector<FiniteElement*> first_half_ele_pt;
13309 Vector<FiniteElement*> second_half_ele_pt;
13311 Vector<int> first_half_face_idx;
13312 Vector<int> second_half_face_idx;
13315 const unsigned n_sub_nodes = tmp_sub_nodes[0].size();
13319 const unsigned n_sub_nodes_half =
static_cast<unsigned>(n_sub_nodes / 2.0);
13324 std::list<Node*>::iterator it_sub = tmp_sub_nodes[0].begin();
13327 first_half_node_pt.push_back(*it_sub);
13333 unsigned counter_nodes = 0;
13334 unsigned counter2 = 0;
13337 for (;it_sub != tmp_sub_nodes[0].end(); it_sub++)
13340 first_half_node_pt.push_back(*it_sub);
13343 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2]);
13344 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2+1]);
13346 first_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2]);
13347 first_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2+1]);
13355 if (counter_nodes == n_sub_nodes_half)
13366 second_half_node_pt.push_back(*it_sub);
13372 for (;it_sub != tmp_sub_nodes[0].end(); it_sub++)
13375 second_half_node_pt.push_back(*it_sub);
13378 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2]);
13379 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2+1]);
13381 second_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2]);
13382 second_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2+1]);
13390 output_sorted_nodes_pt.push_back(first_half_node_pt);
13391 output_sorted_nodes_pt.push_back(second_half_node_pt);
13394 output_boundary_element_pt.push_back(first_half_ele_pt);
13395 output_boundary_element_pt.push_back(second_half_ele_pt);
13398 output_face_index_element.push_back(first_half_face_idx);
13399 output_face_index_element.push_back(second_half_face_idx);
13410 if (input_connect_to_the_left == -3)
13413 output_connect_to_the_left.push_back(-1);
13416 else if (input_connect_to_the_left == -2)
13419 output_connect_to_the_left.push_back(-1);
13424 output_connect_to_the_left.push_back(input_connect_to_the_left);
13430 output_connect_to_the_right.push_back(-1);
13441 output_connect_to_the_left.push_back(tmp_shd_bnd_id-1);
13447 if (n_sub_list == 1)
13449 if (input_connect_to_the_right == -3)
13452 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
13454 else if (input_connect_to_the_right == -2)
13457 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
13459 else if (input_connect_to_the_right == -1)
13462 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
13467 output_connect_to_the_right.push_back(input_connect_to_the_right);
13473 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
13486 output_sorted_nodes_pt.push_back(tmp_sub_nodes[0]);
13489 output_boundary_element_pt.push_back(tmp_sub_bnd_ele_pt[0]);
13492 output_face_index_element.push_back(tmp_sub_face_idx_ele[0]);
13500 if (input_connect_to_the_left == -3)
13503 output_connect_to_the_left.push_back(-1);
13506 else if (input_connect_to_the_left == -2)
13509 output_connect_to_the_left.push_back(tmp_shd_bnd_id+1);
13514 output_connect_to_the_left.push_back(input_connect_to_the_left);
13520 output_connect_to_the_right.push_back(tmp_shd_bnd_id+1);
13528 if (n_sub_list > 1)
13532 left_sub_node_pt = tmp_sub_nodes[1].front();
13533 right_sub_node_pt = tmp_sub_nodes[1].back();
13536 if (left_sub_node_pt == right_sub_node_pt)
13542 std::list<Node*> first_half_node_pt;
13543 std::list<Node*> second_half_node_pt;
13545 Vector<FiniteElement*> first_half_ele_pt;
13546 Vector<FiniteElement*> second_half_ele_pt;
13548 Vector<int> first_half_face_idx;
13549 Vector<int> second_half_face_idx;
13552 const unsigned n_sub_nodes = tmp_sub_nodes[1].size();
13556 const unsigned n_sub_nodes_half =
static_cast<unsigned>(n_sub_nodes / 2.0);
13561 std::list<Node*>::iterator it_sub = tmp_sub_nodes[1].begin();
13564 first_half_node_pt.push_back(*it_sub);
13570 unsigned counter_nodes = 0;
13571 unsigned counter2 = 0;
13574 for (;it_sub != tmp_sub_nodes[1].end(); it_sub++)
13577 first_half_node_pt.push_back(*it_sub);
13579 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[1][counter2]);
13580 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[1][counter2+1]);
13582 first_half_face_idx.push_back(tmp_sub_face_idx_ele[1][counter2]);
13583 first_half_face_idx.push_back(tmp_sub_face_idx_ele[1][counter2+1]);
13591 if (counter_nodes == n_sub_nodes_half)
13602 second_half_node_pt.push_back(*it_sub);
13608 for (;it_sub != tmp_sub_nodes[1].end(); it_sub++)
13611 second_half_node_pt.push_back(*it_sub);
13613 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[1][counter2]);
13614 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[1][counter2+1]);
13616 second_half_face_idx.push_back(tmp_sub_face_idx_ele[1][counter2]);
13617 second_half_face_idx.push_back(tmp_sub_face_idx_ele[1][counter2+1]);
13625 output_sorted_nodes_pt.push_back(first_half_node_pt);
13626 output_sorted_nodes_pt.push_back(second_half_node_pt);
13629 output_boundary_element_pt.push_back(first_half_ele_pt);
13630 output_boundary_element_pt.push_back(second_half_ele_pt);
13633 output_face_index_element.push_back(first_half_face_idx);
13634 output_face_index_element.push_back(second_half_face_idx);
13645 output_connect_to_the_left.push_back(tmp_shd_bnd_id-1);
13650 output_connect_to_the_right.push_back(-1);
13661 output_connect_to_the_left.push_back(tmp_shd_bnd_id-1);
13667 if (n_sub_list == 2)
13670 if (input_connect_to_the_right == -1)
13673 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
13676 else if (input_connect_to_the_right == -2)
13679 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
13682 else if (input_connect_to_the_right == -3)
13685 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
13690 output_connect_to_the_right.push_back(input_connect_to_the_right);
13700 std::stringstream error_message;
13702 <<
"The second sub-list of nodes creates a loop but this is not\n"
13703 <<
"the last list of sub-nodes.\n"
13704 <<
"This configuration is not supported\n";
13705 throw OomphLibError(error_message.str(),
13706 "TriangleMesh::break_loops_on_shared_polyline_helper()",
13707 OOMPH_EXCEPTION_LOCATION);
13718 output_sorted_nodes_pt.push_back(tmp_sub_nodes[1]);
13721 output_boundary_element_pt.push_back(tmp_sub_bnd_ele_pt[1]);
13724 output_face_index_element.push_back(tmp_sub_face_idx_ele[1]);
13732 output_connect_to_the_left.push_back(tmp_shd_bnd_id-1);
13738 if (n_sub_list == 2)
13741 if (input_connect_to_the_right == -3)
13744 output_connect_to_the_right.push_back(-1);
13748 else if (input_connect_to_the_right == -2)
13750 std::stringstream error_message;
13752 <<
"The connection flag to the right ("
13753 << input_connect_to_the_right <<
") indicates a connection\n"
13754 <<
"with the same polyline.\n However, the second sub-list of\n"
13755 <<
"nodes was found not making a loop so no connection with\n"
13756 <<
"itself should be marked\n\n";
13757 throw OomphLibError(error_message.str(),
13758 "TriangleMesh::break_loops_on_shared_polyline_helper()",
13759 OOMPH_EXCEPTION_LOCATION);
13765 output_connect_to_the_right.push_back(input_connect_to_the_right);
13771 output_connect_to_the_right.push_back(tmp_shd_bnd_id+1);
13782 if (n_sub_list > 2)
13786 left_sub_node_pt = tmp_sub_nodes[2].front();
13787 right_sub_node_pt = tmp_sub_nodes[2].back();
13790 if (left_sub_node_pt == right_sub_node_pt)
13796 std::list<Node*> first_half_node_pt;
13797 std::list<Node*> second_half_node_pt;
13799 Vector<FiniteElement*> first_half_ele_pt;
13800 Vector<FiniteElement*> second_half_ele_pt;
13802 Vector<int> first_half_face_idx;
13803 Vector<int> second_half_face_idx;
13806 const unsigned n_sub_nodes = tmp_sub_nodes[2].size();
13810 const unsigned n_sub_nodes_half =
static_cast<unsigned>(n_sub_nodes / 2.0);
13815 std::list<Node*>::iterator it_sub = tmp_sub_nodes[2].begin();
13818 first_half_node_pt.push_back(*it_sub);
13824 unsigned counter_nodes = 0;
13825 unsigned counter2 = 0;
13828 for (;it_sub != tmp_sub_nodes[2].end(); it_sub++)
13831 first_half_node_pt.push_back(*it_sub);
13833 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[2][counter2]);
13834 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[2][counter2+1]);
13836 first_half_face_idx.push_back(tmp_sub_face_idx_ele[2][counter2]);
13837 first_half_face_idx.push_back(tmp_sub_face_idx_ele[2][counter2+1]);
13845 if (counter_nodes == n_sub_nodes_half)
13856 second_half_node_pt.push_back(*it_sub);
13862 for (;it_sub != tmp_sub_nodes[2].end(); it_sub++)
13865 second_half_node_pt.push_back(*it_sub);
13867 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[2][counter2]);
13868 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[2][counter2+1]);
13870 second_half_face_idx.push_back(tmp_sub_face_idx_ele[2][counter2]);
13871 second_half_face_idx.push_back(tmp_sub_face_idx_ele[2][counter2+1]);
13879 output_sorted_nodes_pt.push_back(first_half_node_pt);
13880 output_sorted_nodes_pt.push_back(second_half_node_pt);
13883 output_boundary_element_pt.push_back(first_half_ele_pt);
13884 output_boundary_element_pt.push_back(second_half_ele_pt);
13887 output_face_index_element.push_back(first_half_face_idx);
13888 output_face_index_element.push_back(second_half_face_idx);
13896 output_connect_to_the_left.push_back(tmp_shd_bnd_id-1);
13901 output_connect_to_the_right.push_back(-1);
13912 output_connect_to_the_left.push_back(tmp_shd_bnd_id-1);
13916 if (input_connect_to_the_right == -3)
13919 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
13921 else if (input_connect_to_the_right == -2)
13924 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
13926 else if (input_connect_to_the_right == -1)
13929 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
13934 output_connect_to_the_right.push_back(input_connect_to_the_right);
13947 output_sorted_nodes_pt.push_back(tmp_sub_nodes[2]);
13950 output_boundary_element_pt.push_back(tmp_sub_bnd_ele_pt[2]);
13953 output_face_index_element.push_back(tmp_sub_face_idx_ele[2]);
13961 output_connect_to_the_left.push_back(tmp_shd_bnd_id-1);
13966 if (input_connect_to_the_right == -3)
13968 std::stringstream error_message;
13970 <<
"The connection flag to the right ("
13971 << input_connect_to_the_right <<
") indicates 'no connection and\n"
13972 <<
"stop adding nodes'.\n However, the thrid sub-list of\n"
13973 <<
"nodes must have a connection to the right with the same\n"
13974 <<
"shared polyline or with any other polyline\n\n";
13975 throw OomphLibError(error_message.str(),
13976 "TriangleMesh::break_loops_on_shared_polyline_helper()",
13977 OOMPH_EXCEPTION_LOCATION);
13979 else if (input_connect_to_the_right == -1)
13981 std::stringstream error_message;
13983 <<
"The connection flag to the right ("
13984 << input_connect_to_the_right <<
") indicates 'no connection.\n"
13985 <<
"However, the thrid sub-list of nodes must have a connection\n"
13986 <<
"to the right with the same shared polyline or with any other\n"
13988 throw OomphLibError(error_message.str(),
13989 "TriangleMesh::break_loops_on_shared_polyline_helper()",
13990 OOMPH_EXCEPTION_LOCATION);
13993 else if (input_connect_to_the_right == -2)
13996 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
14001 output_connect_to_the_right.push_back(input_connect_to_the_right);
14017 template<
class ELEMENT>
14020 const unsigned &initial_shd_bnd_id,
14021 std::list<Node*> &input_nodes,
14022 Vector<FiniteElement*> &input_boundary_element_pt,
14023 Vector<FiniteElement*> &input_boundary_face_element_pt,
14024 Vector<int> &input_face_index_element,
14025 const int &input_connect_to_the_left,
14026 const int &input_connect_to_the_right,
14027 Vector<std::list<Node*> > &output_sorted_nodes_pt,
14028 Vector<Vector<FiniteElement*> > &output_boundary_element_pt,
14029 Vector<Vector<FiniteElement*> > &output_boundary_face_element_pt,
14030 Vector<Vector<int> > &output_face_index_element,
14031 Vector<int> &output_connect_to_the_left,
14032 Vector<int> &output_connect_to_the_right)
14035 Node* left_node_pt = input_nodes.front();
14036 Node* right_node_pt = input_nodes.back();
14040 Vector<std::list<Node*> > tmp_sub_nodes;
14041 Vector<Vector<FiniteElement*> > tmp_sub_bnd_ele_pt;
14042 Vector<Vector<FiniteElement*> > tmp_sub_bnd_face_ele_pt;
14043 Vector<Vector<int> > tmp_sub_face_idx_ele;
14046 std::list<Node*>::iterator it = input_nodes.begin();
14049 unsigned counter = 0;
14052 while(it != input_nodes.end())
14057 if (it == input_nodes.end())
14069 std::list<Node*> sub_nodes;
14072 Vector<FiniteElement*> sub_bnd_ele_pt;
14075 Vector<FiniteElement*> sub_bnd_face_ele_pt;
14078 Vector<int> sub_face_idx_ele;
14081 sub_nodes.push_back(*it);
14091 sub_nodes.push_back((*it));
14094 sub_bnd_ele_pt.push_back(input_boundary_element_pt[counter]);
14097 sub_bnd_face_ele_pt.push_back(input_boundary_face_element_pt[counter]);
14100 sub_face_idx_ele.push_back(input_face_index_element[counter]);
14107 }
while((*it) != left_node_pt &&
14108 (*it) != right_node_pt &&
14109 it != input_nodes.end());
14112 tmp_sub_nodes.push_back(sub_nodes);
14115 tmp_sub_bnd_ele_pt.push_back(sub_bnd_ele_pt);
14117 tmp_sub_bnd_face_ele_pt.push_back(sub_bnd_face_ele_pt);
14119 tmp_sub_face_idx_ele.push_back(sub_face_idx_ele);
14127 const unsigned n_sub_list = tmp_sub_nodes.size();
14130 if (n_sub_list > 1)
14132 std::stringstream error_message;
14134 <<
"The number of sub-list of nodes created from the shared\n"
14135 <<
"polyline with loops was (" << n_sub_list <<
").\n"
14136 <<
"We can only handle one list which may still contain loops\n"
14137 <<
"(or repeated nodes)\n";
14138 throw OomphLibError(error_message.str(),
14139 "TriangleMesh::break_loops_on_shared_polyline_load_balance_helper()",
14140 OOMPH_EXCEPTION_LOCATION);
14146 if (n_sub_list == 1 && (left_node_pt != right_node_pt))
14154 output_sorted_nodes_pt = tmp_sub_nodes;
14156 output_boundary_element_pt = tmp_sub_bnd_ele_pt;
14158 output_boundary_face_element_pt = tmp_sub_bnd_face_ele_pt;
14160 output_face_index_element = tmp_sub_face_idx_ele;
14166 if (input_connect_to_the_left == -2)
14168 std::stringstream error_message;
14170 <<
"The connection flag to the left ("
14171 << input_connect_to_the_left <<
") indicates a connection\n"
14172 <<
"with the same polyline.\n However, only one sub-polyline was "
14173 <<
"found and no loops\nwere identified\n\n";
14174 throw OomphLibError(error_message.str(),
14175 "TriangleMesh::break_loops_on_shared_polyline_load_balance_helper()",
14176 OOMPH_EXCEPTION_LOCATION);
14181 if (input_connect_to_the_left == -3)
14183 output_connect_to_the_left.push_back(-1);
14187 output_connect_to_the_left.push_back(input_connect_to_the_left);
14191 if (input_connect_to_the_right == -2)
14193 std::stringstream error_message;
14195 <<
"The connection flag to the right ("
14196 << input_connect_to_the_right <<
") indicates a connection\n"
14197 <<
"with the same polyline.\n However, only one sub-polyline was "
14198 <<
"found and no loops\nwere identified\n\n";
14199 throw OomphLibError(error_message.str(),
14200 "TriangleMesh::break_loops_on_shared_polyline_load_balance_helper()",
14201 OOMPH_EXCEPTION_LOCATION);
14206 if (input_connect_to_the_right == -3)
14208 output_connect_to_the_right.push_back(-1);
14212 output_connect_to_the_right.push_back(input_connect_to_the_right);
14220 unsigned tmp_shd_bnd_id = initial_shd_bnd_id;
14228 Node* left_sub_node_pt = tmp_sub_nodes[0].front();
14229 Node* right_sub_node_pt = tmp_sub_nodes[0].back();
14232 if (left_sub_node_pt == right_sub_node_pt)
14238 std::list<Node*> first_half_node_pt;
14239 std::list<Node*> second_half_node_pt;
14241 Vector<FiniteElement*> first_half_ele_pt;
14242 Vector<FiniteElement*> second_half_ele_pt;
14244 Vector<FiniteElement*> first_half_ele_face_pt;
14245 Vector<FiniteElement*> second_half_ele_face_pt;
14247 Vector<int> first_half_face_idx;
14248 Vector<int> second_half_face_idx;
14251 const unsigned n_sub_nodes = tmp_sub_nodes[0].size();
14255 const unsigned n_sub_nodes_half =
static_cast<unsigned>(n_sub_nodes / 2.0);
14260 std::list<Node*>::iterator it_sub = tmp_sub_nodes[0].begin();
14263 first_half_node_pt.push_back(*it_sub);
14269 unsigned counter_nodes = 0;
14270 unsigned counter2 = 0;
14273 for (;it_sub != tmp_sub_nodes[0].end(); it_sub++)
14276 first_half_node_pt.push_back(*it_sub);
14279 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2]);
14281 first_half_ele_face_pt.push_back(tmp_sub_bnd_face_ele_pt[0][counter2]);
14283 first_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2]);
14291 if (counter_nodes == n_sub_nodes_half)
14302 second_half_node_pt.push_back(*it_sub);
14308 for (;it_sub != tmp_sub_nodes[0].end(); it_sub++)
14311 second_half_node_pt.push_back(*it_sub);
14314 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2]);
14316 second_half_ele_face_pt.push_back(tmp_sub_bnd_face_ele_pt[0][counter2]);
14318 second_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2]);
14326 output_sorted_nodes_pt.push_back(first_half_node_pt);
14327 output_sorted_nodes_pt.push_back(second_half_node_pt);
14330 output_boundary_element_pt.push_back(first_half_ele_pt);
14331 output_boundary_element_pt.push_back(second_half_ele_pt);
14334 output_boundary_face_element_pt.push_back(first_half_ele_face_pt);
14335 output_boundary_face_element_pt.push_back(second_half_ele_face_pt);
14338 output_face_index_element.push_back(first_half_face_idx);
14339 output_face_index_element.push_back(second_half_face_idx);
14350 if (input_connect_to_the_left == -3)
14353 output_connect_to_the_left.push_back(-1);
14356 else if (input_connect_to_the_left == -2)
14359 output_connect_to_the_left.push_back(-1);
14364 output_connect_to_the_left.push_back(input_connect_to_the_left);
14370 output_connect_to_the_right.push_back(-1);
14381 output_connect_to_the_left.push_back(tmp_shd_bnd_id-1);
14387 if (n_sub_list == 1)
14389 if (input_connect_to_the_right == -3)
14392 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
14394 else if (input_connect_to_the_right == -2)
14397 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
14399 else if (input_connect_to_the_right == -1)
14402 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
14407 output_connect_to_the_right.push_back(input_connect_to_the_right);
14413 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
14423 std::stringstream error_message;
14425 <<
"The initial and final node in the current shared polyline are not\n"
14426 <<
"the same and the number of sublists is ("<< n_sub_list <<
").\n"
14427 <<
"We can not handle more than one sublist in the method to break\n"
14428 <<
"loops at the load balance stage\n\n";
14429 throw OomphLibError(error_message.str(),
14430 "TriangleMesh::break_loops_on_shared_polyline_load_balance_helper()",
14431 OOMPH_EXCEPTION_LOCATION);
14442 template<
class ELEMENT>
14445 const unsigned &shd_bnd_id,
14446 const unsigned &iproc,
14447 const unsigned &jproc,
14448 std::list<Node*> &sorted_nodes,
14449 const int &root_edge_bnd_id,
14450 Vector<FiniteElement*> &bulk_bnd_ele_pt,
14451 Vector<int> &face_index_ele,
14452 Vector<Vector<TriangleMeshPolyLine *> >
14453 &unsorted_polylines_pt,
14454 const int &connect_to_the_left_flag,
14455 const int &connect_to_the_right_flag)
14466 Shared_boundaries_ids[iproc][jproc].push_back(shd_bnd_id);
14469 Shared_boundaries_ids[jproc][iproc].push_back(shd_bnd_id);
14473 Vector<unsigned> processors(2);
14474 processors[0] = iproc;
14475 processors[1] = jproc;
14476 Shared_boundary_from_processors[shd_bnd_id] = processors;
14482 if (iproc == my_rank || jproc == my_rank)
14489 const unsigned n_nodes = sorted_nodes.size();
14491 Vector<Vector<double> > vertices(n_nodes);
14494 unsigned counter = 0;
14496 for (std::list<Node*>::iterator it = sorted_nodes.begin();
14497 it != sorted_nodes.end(); it++)
14499 vertices[counter].resize(2);
14500 vertices[counter][0] = (*it)->x(0);
14501 vertices[counter][1] = (*it)->x(1);
14508 TriangleMeshPolyLine *polyline_pt =
14509 new TriangleMeshPolyLine(vertices, shd_bnd_id);
14517 if (root_edge_bnd_id != -1)
14521 Shared_boundary_overlaps_internal_boundary[shd_bnd_id] =
14522 static_cast<unsigned>(root_edge_bnd_id);
14530 const unsigned n_shared_boundary_elements = bulk_bnd_ele_pt.size();
14534 const unsigned n_face_index = face_index_ele.size();
14535 if (n_shared_boundary_elements != n_face_index)
14537 std::ostringstream error_message;
14539 <<
"The number of shared boundary elements is different from the\n"
14540 <<
"number of face indexes associated to the shared boundary\n"
14542 <<
"Number of shared boundary elements: ("
14543 << n_shared_boundary_elements <<
")\n"
14544 <<
"Number of face indexes: (" << n_face_index <<
")\n\n";
14545 throw OomphLibError(error_message.str(),
14546 "TriangleMesh::create_shared_polyline()",
14547 OOMPH_EXCEPTION_LOCATION);
14553 for (
unsigned i = 0 ; i < n_shared_boundary_elements; i++)
14555 add_shared_boundary_element(shd_bnd_id, bulk_bnd_ele_pt[i]);
14556 add_face_index_at_shared_boundary(shd_bnd_id, face_index_ele[i]);
14560 for (std::list<Node*>::iterator it = sorted_nodes.begin();
14561 it != sorted_nodes.end(); it++)
14563 add_shared_boundary_node(shd_bnd_id, (*it));
14571 this->Boundary_curve_section_pt[shd_bnd_id] = polyline_pt;
14576 const unsigned n_procs = unsorted_polylines_pt.size();
14581 unsorted_polylines_pt[iproc].push_back(polyline_pt);
14585 unsorted_polylines_pt[jproc].push_back(polyline_pt);
14591 unsorted_polylines_pt[0].push_back(polyline_pt);
14595 this->Free_curve_section_pt.insert(polyline_pt);
14605 if (connect_to_the_left_flag < 0)
14608 if (connect_to_the_left_flag != -1)
14610 std::ostringstream error_message;
14612 <<
"The only accepted values for the connection flags are:\n"
14613 <<
"POSITIVE values or -1, any other value is rejected, please\n"
14614 <<
"check that you previously called the methods to deal with\n"
14615 <<
"other flag values\n"
14616 <<
"The current flag value for connection to the left is: ("
14617 << connect_to_the_left_flag<<
")\n\n";
14618 throw OomphLibError(error_message.str(),
14619 "TriangleMesh::create_shared_polyline()",
14620 OOMPH_EXCEPTION_LOCATION);
14625 if (connect_to_the_right_flag < 0)
14628 if (connect_to_the_right_flag != -1)
14630 std::ostringstream error_message;
14632 <<
"The only accepted values for the connection flags are:\n"
14633 <<
"POSITIVE values or -1, any other value is rejected, please\n"
14634 <<
"check that you previously called the methods to deal with\n"
14635 <<
"other flag values\n"
14636 <<
"The current flag value for connection to the right is: ("
14637 << connect_to_the_right_flag<<
")\n\n";
14638 throw OomphLibError(error_message.str(),
14639 "TriangleMesh::create_shared_polyline()",
14640 OOMPH_EXCEPTION_LOCATION);
14646 if (connect_to_the_left_flag != -1)
14649 const unsigned bnd_id_connection_to_the_left =
14650 static_cast<unsigned>(connect_to_the_left_flag);
14652 polyline_pt->set_initial_vertex_connected();
14654 polyline_pt->initial_vertex_connected_bnd_id() =
14655 bnd_id_connection_to_the_left;
14657 polyline_pt->initial_vertex_connected_n_chunk() = 0;
14662 if (connect_to_the_right_flag != -1)
14665 const unsigned bnd_id_connection_to_the_right =
14666 static_cast<unsigned>(connect_to_the_right_flag);
14668 polyline_pt->set_final_vertex_connected();
14670 polyline_pt->final_vertex_connected_bnd_id() =
14671 bnd_id_connection_to_the_right;
14673 polyline_pt->final_vertex_connected_n_chunk() = 0;
14685 template <
class ELEMENT>
14688 Vector<Vector<unsigned> >
14689 &ntmp_boundary_elements_in_region,
14690 Vector<FiniteElement*> &deleted_elements)
14693 const unsigned nbound = this->nboundary();
14696 const unsigned n_regions = this->nregion();
14699 for (
unsigned b = 0; b < nbound; b++)
14704 const unsigned nbound_ele = this->nboundary_element(b);
14706 Vector<FiniteElement*> backed_up_boundary_element_pt(nbound_ele);
14707 Vector<int> backed_up_face_index_at_boundary(nbound_ele);
14708 for (
unsigned e = 0; e < nbound_ele; e++)
14711 backed_up_boundary_element_pt[e] = this->boundary_element_pt(b, e);
14713 backed_up_face_index_at_boundary[e] =
14714 this->face_index_at_boundary(b, e);
14718 Vector<Vector<FiniteElement*> >
14719 backed_up_boundary_region_element_pt(n_regions);
14720 Vector<Vector<int> > backed_up_face_index_at_boundary_region(n_regions);
14724 for (
unsigned ir = 0; ir < n_regions; ir++)
14727 const unsigned region_id =
14728 static_cast<unsigned>(this->region_attribute(ir));
14730 const unsigned nbnd_region_ele =
14731 this->nboundary_element_in_region(b, region_id);
14734 for (
unsigned e = 0; e < nbnd_region_ele; e++)
14737 backed_up_boundary_region_element_pt[ir][e] =
14738 this->boundary_element_in_region_pt(b, region_id, e);
14741 backed_up_face_index_at_boundary_region[ir][e] =
14742 this->face_index_at_boundary_in_region(b, region_id, e);
14748 this->Boundary_element_pt[b].clear();
14749 this->Face_index_at_boundary[b].clear();
14752 this->Boundary_region_element_pt[b].clear();
14753 this->Face_index_region_at_boundary[b].clear();
14762 const unsigned nold_bnd_ele = ntmp_boundary_elements[b];
14764 for (
unsigned e = 0; e < nold_bnd_ele; e++)
14766 FiniteElement* tmp_ele_pt = backed_up_boundary_element_pt[e];
14768 Vector<FiniteElement*>::iterator it =
14769 std::find(deleted_elements.begin(),
14770 deleted_elements.end(),
14774 if (it == deleted_elements.end())
14776 FiniteElement* add_ele_pt = backed_up_boundary_element_pt[e];
14777 this->Boundary_element_pt[b].push_back(add_ele_pt);
14778 const int face_index = backed_up_face_index_at_boundary[e];
14779 this->Face_index_at_boundary[b].push_back(face_index);
14787 for (
unsigned ir = 0; ir < n_regions; ir++)
14790 const unsigned region_id =
14791 static_cast<unsigned>(this->region_attribute(ir));
14794 const unsigned nold_bnd_region_ele =
14795 ntmp_boundary_elements_in_region[b][ir];
14799 for (
unsigned e = 0; e < nold_bnd_region_ele; e++)
14802 FiniteElement* tmp_ele_pt =
14803 backed_up_boundary_region_element_pt[ir][e];
14805 Vector<FiniteElement*>::iterator it =
14806 std::find(deleted_elements.begin(),
14807 deleted_elements.end(),
14811 if (it == deleted_elements.end())
14813 FiniteElement* add_ele_pt =
14814 backed_up_boundary_region_element_pt[ir][e];
14815 this->Boundary_region_element_pt[b][region_id].push_back(add_ele_pt);
14816 const int face_index = backed_up_face_index_at_boundary_region[ir][e];
14817 this->Face_index_region_at_boundary[b][region_id].
14818 push_back(face_index);
14830 for (
unsigned e = nold_bnd_ele; e < nbound_ele; e++)
14832 FiniteElement* add_ele_pt = backed_up_boundary_element_pt[e];
14833 this->Boundary_element_pt[b].push_back(add_ele_pt);
14834 const int face_index = backed_up_face_index_at_boundary[e];
14835 this->Face_index_at_boundary[b].push_back(face_index);
14841 for (
unsigned ir = 0; ir < n_regions; ir++)
14844 const unsigned region_id =
14845 static_cast<unsigned>(this->region_attribute(ir));
14848 const unsigned nold_bnd_region_ele =
14849 ntmp_boundary_elements_in_region[b][ir];
14852 const unsigned nbnd_region_ele =
14853 this->nboundary_element_in_region(b, region_id);
14857 for (
unsigned e = nold_bnd_region_ele; e < nbnd_region_ele; e++)
14859 FiniteElement* add_ele_pt = backed_up_boundary_region_element_pt[ir][e];
14860 this->Boundary_region_element_pt[b][region_id].push_back(add_ele_pt);
14861 const int face_index = backed_up_face_index_at_boundary_region[ir][e];
14862 this->Face_index_region_at_boundary[b][region_id].push_back(face_index);
14870 Lookup_for_elements_next_boundary_is_setup=
true;
14874 #endif // OOMPH_HAS_MPI
14876 #ifdef OOMPH_HAS_TRIANGLE_LIB
14881 template <
class ELEMENT>
14883 TriangulateIO& triangulate_io,
14884 const Vector<double>& target_area,
14885 struct TriangulateIO& triangle_refine)
14889 TriangleHelper::initialise_triangulateio(triangle_refine);
14893 unsigned n_points = triangulate_io.numberofpoints;
14894 triangle_refine.numberofpoints=n_points;
14896 unsigned n_segments=triangulate_io.numberofsegments;
14897 triangle_refine.numberofsegments=n_segments;
14900 triangle_refine.pointlist =
14901 (
double *) malloc(triangulate_io.numberofpoints * 2 *
sizeof(
double));
14902 triangle_refine.pointmarkerlist =
14903 (
int *) malloc(triangulate_io.numberofpoints *
sizeof(
int));
14904 triangle_refine.segmentlist =
14905 (
int *) malloc(triangulate_io.numberofsegments * 2 *
sizeof(
int));
14906 triangle_refine.segmentmarkerlist =
14907 (
int *) malloc(triangulate_io.numberofsegments *
sizeof(
int));
14911 Vector<double> x_coord (n_points);
14912 Vector<double> y_coord (n_points);
14914 for(
unsigned count_point=0;count_point<n_points*2;count_point++)
14916 triangle_refine.pointlist[count_point]=
14917 triangulate_io.pointlist[count_point];
14921 if (count_point%2==0)
14923 x_coord[count_point/2] = triangulate_io.pointlist[count_point];
14927 y_coord[(count_point-1)/2] = triangulate_io.pointlist[count_point];
14932 for(
unsigned count_marker=0;count_marker<n_points;count_marker++)
14934 triangle_refine.pointmarkerlist[count_marker]=
14935 triangulate_io.pointmarkerlist[count_marker];
14939 for(
unsigned count_seg=0;count_seg<n_segments*2;count_seg++)
14941 triangle_refine.segmentlist[count_seg]=
14942 triangulate_io.segmentlist[count_seg];
14946 for(
unsigned count_markers=0;count_markers<n_segments;count_markers++)
14948 triangle_refine.segmentmarkerlist[count_markers]=
14949 triangulate_io.segmentmarkerlist[count_markers];
14953 unsigned n_holes = triangulate_io.numberofholes;
14954 triangle_refine.numberofholes = n_holes;
14956 triangle_refine.holelist =
14957 (
double*) malloc(triangulate_io.numberofholes * 2 *
sizeof(
double));
14960 for(
unsigned count_hole=0;count_hole<n_holes*2;count_hole++)
14962 triangle_refine.holelist[count_hole] = triangulate_io.holelist[count_hole];
14966 unsigned n_triangles = triangulate_io.numberoftriangles;
14967 triangle_refine.numberoftriangles = n_triangles;
14970 if (n_triangles!=target_area.size())
14972 std::stringstream err;
14973 err <<
"Number of triangles in triangulate_io="
14974 << n_triangles <<
" doesn't match\n"
14975 <<
"size of target area vector ("
14976 << target_area.size() <<
")\n";
14977 throw OomphLibError(
14979 OOMPH_CURRENT_FUNCTION,
14980 OOMPH_EXCEPTION_LOCATION);
14984 unsigned n_corners = triangulate_io.numberofcorners;
14985 triangle_refine.numberofcorners = n_corners;
14987 triangle_refine.trianglelist =
14988 (
int *) malloc(triangulate_io.numberoftriangles * 3 *
sizeof(
int));
14991 for(
unsigned count_tri=0;count_tri<n_triangles*3;count_tri++)
14993 triangle_refine.trianglelist[count_tri]=
14994 triangulate_io.trianglelist[count_tri];
14998 triangle_refine.trianglearealist =
14999 (
double *) malloc(triangulate_io.numberoftriangles *
sizeof(
double));
15000 for(
unsigned count_area=0;count_area<n_triangles;count_area++)
15002 triangle_refine.trianglearealist[count_area]=target_area[count_area];
15006 triangle_refine.numberoftriangleattributes =
15007 triangulate_io.numberoftriangleattributes;
15009 triangle_refine.triangleattributelist =
15011 triangulate_io.numberoftriangles *
15012 triangulate_io.numberoftriangleattributes *
sizeof(
double));
15013 for(
unsigned count_attribute=0;
15014 count_attribute<(n_triangles*triangulate_io.numberoftriangleattributes);
15017 triangle_refine.triangleattributelist[count_attribute] =
15018 triangulate_io.triangleattributelist[count_attribute];
15023 #ifdef OOMPH_HAS_MPI
15038 const std::pair<double, double> &rhs)
const
15040 double diff_y=lhs.second-rhs.second;
15051 double diff_x=lhs.first-rhs.first;
15052 if (fabs(diff_x)<
Tol)
15054 std::ostringstream warning_message;
15056 <<
"Dodgy \"lower left\" (lexicographic) comparison "
15057 <<
"of points with cooordinates: "
15058 <<
" lhs = ( " << lhs.first <<
" , " << lhs.second <<
" ) \n"
15059 <<
" rhs = ( " << rhs.first <<
" , " << rhs.second <<
" ) \n"
15060 <<
"x and y coordinates differ by less than tolerance!\n"
15061 <<
"diff_x = " << diff_x <<
"\n"
15062 <<
"diff_y = " << diff_y <<
"\n"
15063 <<
"Tol = " <<
Tol <<
"\n";
15064 OomphLibError(warning_message.str(),
15065 OOMPH_CURRENT_FUNCTION,
15066 OOMPH_EXCEPTION_LOCATION);
15069 if (lhs.first < rhs.first)
15126 template <
class ELEMENT>
15130 Vector<unsigned> my_rank_shared_boundaries_ids;
15131 this->shared_boundaries_in_this_processor(my_rank_shared_boundaries_ids);
15134 const unsigned nmy_rank_shd_bnd = my_rank_shared_boundaries_ids.size();
15137 for (
unsigned i = 0; i < nmy_rank_shd_bnd; i++)
15142 std::map<std::pair<double, double>, Node*,
classcomp> sorted_nodes_pt;
15149 double min_distance_squared=DBL_MAX;
15154 const unsigned b = my_rank_shared_boundaries_ids[i];
15157 const unsigned nbnd_node = this->nshared_boundary_node(b);
15161 for (
unsigned i_node = 0; i_node < nbnd_node; i_node++)
15163 Node* node_pt = this->shared_boundary_node_pt(b, i_node);
15164 std::pair<double, double> vertex = std::make_pair(node_pt->x(0),
15166 sorted_nodes_pt[vertex] = node_pt;
15173 for (
unsigned j_node = 0; j_node < nbnd_node; j_node++)
15175 if (i_node!=j_node)
15177 Node* node2_pt = this->shared_boundary_node_pt(b, j_node);
15180 double squared_distance=0.0;
15181 for (
unsigned ii=0;ii<2;ii++)
15184 (node_pt->x(ii)-node2_pt->x(ii))*
15185 (node_pt->x(ii)-node2_pt->x(ii));
15187 if (squared_distance<min_distance_squared)
15189 min_distance_squared=squared_distance;
15196 std::ostringstream warning_message;
15198 <<
"Minimum distance between nodes on boundary " << b <<
"\n"
15199 <<
"is " << sqrt(min_distance_squared) <<
" which is less than "
15201 <<
"This may screw up the ordering of the nodes on shared boundaries\n";
15202 OomphLibWarning(warning_message.str(),
15203 OOMPH_CURRENT_FUNCTION,
15204 OOMPH_EXCEPTION_LOCATION);
15211 unsigned counter = 0;
15213 this->Sorted_shared_boundary_node_pt[b].resize(nbnd_node);
15219 for (std::map<std::pair<double, double>, Node*>::iterator it_map
15220 = sorted_nodes_pt.begin(); it_map != sorted_nodes_pt.end(); it_map++)
15223 this->Sorted_shared_boundary_node_pt[b][counter++] = (*it_map).second;
15235 template <
class ELEMENT>
15238 const bool update_elements,
15239 const bool flush_nodes,
15240 const bool update_nodes)
15243 const unsigned my_rank = this->communicator_pt()->my_rank();
15249 const unsigned initial_id = this->initial_shared_boundary_id();
15252 const unsigned final_id = this->final_shared_boundary_id();
15254 if (flush_elements)
15257 this->flush_shared_boundary_element();
15259 this->flush_face_index_at_shared_boundary();
15265 this->flush_shared_boundary_node();
15268 for (
unsigned b = initial_id; b < final_id; b++)
15271 Vector<unsigned> procs_from_shrd_bnd;
15272 procs_from_shrd_bnd = this->shared_boundary_from_processors(b);
15273 bool current_processor_has_b_boundary =
false;
15274 const unsigned n_procs_from_shrd_bnd = procs_from_shrd_bnd.size();
15275 for (
unsigned p = 0; p < n_procs_from_shrd_bnd; p++)
15277 if (procs_from_shrd_bnd[p] == my_rank)
15279 current_processor_has_b_boundary =
true;
15284 if (current_processor_has_b_boundary)
15286 if (update_elements)
15288 const unsigned nboundary_ele = this->nboundary_element(b);
15289 for (
unsigned e = 0; e < nboundary_ele; e++)
15293 FiniteElement* bnd_ele_pt = this->boundary_element_pt(b, e);
15294 this->add_shared_boundary_element(b, bnd_ele_pt);
15296 int face_index = this->face_index_at_boundary(b, e);
15297 this->add_face_index_at_shared_boundary(b, face_index);
15305 const unsigned nboundary_node = this->nboundary_node(b);
15306 for (
unsigned n = 0; n < nboundary_node; n++)
15308 Node* bnd_node_pt = this->boundary_node_pt(b, n);
15309 this->add_shared_boundary_node(b, bnd_node_pt);
15322 template <
class ELEMENT>
15326 unsigned nproc = this->communicator_pt()->nproc();
15328 unsigned my_rank = this->communicator_pt()->my_rank();
15331 double tt_start = 0.0;
15333 if (Global_timings::Doc_comprehensive_timings)
15335 tt_start=TimingHelpers::timer();
15345 Vector<Vector<Vector<std::map<unsigned, Node*> > > >
15346 other_proc_shd_bnd_node_pt(nproc);
15348 for (
unsigned iproc = 0; iproc < nproc; iproc++)
15351 other_proc_shd_bnd_node_pt[iproc].resize(nproc);
15352 for (
unsigned jproc = 0; jproc < nproc; jproc++)
15355 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
15356 const unsigned final_shd_bnd_id = this->final_shared_boundary_id();
15357 const unsigned nshared_bound = final_shd_bnd_id - initial_shd_bnd_id;
15358 other_proc_shd_bnd_node_pt[iproc][jproc].resize(nshared_bound);
15367 Vector<Vector<Vector<unsigned> > > global_node_names;
15371 std::map<Vector<unsigned>,
unsigned> node_name_to_global_index;
15374 Vector<Node*> global_shared_node_pt;
15378 double t_start_global_node_names_and_shared_nodes =
15379 TimingHelpers::timer();
15384 compute_global_node_names_and_shared_nodes(other_proc_shd_bnd_node_pt,
15386 node_name_to_global_index,
15387 global_shared_node_pt);
15390 const unsigned n_ele = this->nelement();
15392 if (Print_timings_level_adaptation>1)
15396 double t_final_global_node_names_and_shared_nodes =
15397 TimingHelpers::timer() - t_start_global_node_names_and_shared_nodes;
15398 oomph_info <<
"CPU for computing global node names and shared nodes "
15399 <<
"[n_ele="<< n_ele <<
"]: "
15400 << t_final_global_node_names_and_shared_nodes << std::endl;
15417 double t_start_send_info_shd_nodes_on_original_bnds =
15418 TimingHelpers::timer();
15422 send_boundary_node_info_of_shared_nodes(global_node_names,
15423 node_name_to_global_index,
15424 global_shared_node_pt);
15426 if (Print_timings_level_adaptation>1)
15431 <<
"CPU for sending info. of shared nodes on original boundaries: "
15432 <<TimingHelpers::timer()-t_start_send_info_shd_nodes_on_original_bnds
15455 Vector<Vector<Vector<FiniteElement*> > > ele_with_node_on_shd_bnd_pt(nproc);
15460 for (
unsigned iproc = 0; iproc < nproc; iproc++)
15462 const unsigned n_shd_bnd_iproc = this->nshared_boundaries(my_rank, iproc);
15463 ele_with_node_on_shd_bnd_pt[iproc].resize(n_shd_bnd_iproc);
15470 for (
unsigned e = 0; e < n_ele; e++)
15473 FiniteElement* ele_pt = this->finite_element_pt(e);
15475 const unsigned n_nodes = ele_pt->nnode();
15478 for (
unsigned n = 0; n < n_nodes; n++)
15481 Node* node_pt = ele_pt->node_pt(n);
15487 for (
unsigned iproc = 0; iproc < nproc; iproc++)
15492 const unsigned n_shd_bnd_iproc =
15493 this->nshared_boundaries(my_rank, iproc);
15496 if (iproc != my_rank && n_shd_bnd_iproc > 0)
15500 Vector<unsigned> shd_bnd_ids =
15501 this->shared_boundaries_ids(my_rank, iproc);
15504 for (
unsigned isb = 0; isb < n_shd_bnd_iproc; isb++)
15506 const unsigned shd_bnd_id = shd_bnd_ids[isb];
15507 const unsigned n_ele_shd_bnd =
15508 this->nshared_boundary_element(shd_bnd_id);
15512 if (n_ele_shd_bnd > 0 &&
15513 this->is_node_on_shared_boundary(shd_bnd_id, node_pt))
15517 ele_with_node_on_shd_bnd_pt[iproc][isb].push_back(ele_pt);
15557 Vector<Vector<Node*> > iproc_currently_created_nodes_pt(nproc);
15560 double t_start_regenerate_halo_ed_elements_nodes_first_stage =
15561 TimingHelpers::timer();
15564 for (
unsigned iproc = 0; iproc < nproc; iproc++)
15567 if (iproc != my_rank)
15570 const unsigned nshared_boundaries_with_iproc =
15571 this->nshared_boundaries(my_rank, iproc);
15573 if (nshared_boundaries_with_iproc > 0)
15585 Flat_packed_unsigneds.clear();
15586 Flat_packed_doubles.clear();
15587 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15588 Flat_packed_unsigneds_string.clear();
15592 Vector<unsigned> bound_shared_with_iproc;
15593 bound_shared_with_iproc = this->shared_boundaries_ids(my_rank, iproc);
15596 for (
unsigned bs = 0; bs < nshared_boundaries_with_iproc; bs++)
15598 const unsigned bnd_id = bound_shared_with_iproc[bs];
15600 const unsigned nel_bnd = this->nshared_boundary_element(bnd_id);
15604 Vector<FiniteElement*> haloed_element;
15611 std::map<FiniteElement*,bool> already_added;
15614 for (
unsigned e = 0; e < nel_bnd; e++)
15617 FiniteElement* ele_pt =
15618 this->shared_boundary_element_pt(bnd_id, e);
15623 if (!already_added[ele_pt])
15626 haloed_element.push_back(ele_pt);
15628 already_added[ele_pt] =
true;
15639 const unsigned n_ele_with_node_on_shd_bnd =
15640 ele_with_node_on_shd_bnd_pt[iproc][bs].size();
15643 for (
unsigned iele = 0; iele < n_ele_with_node_on_shd_bnd; iele++)
15646 FiniteElement* ele_pt =
15647 ele_with_node_on_shd_bnd_pt[iproc][bs][iele];
15649 if (!already_added[ele_pt])
15652 haloed_element.push_back(ele_pt);
15654 already_added[ele_pt] =
true;
15662 const unsigned nhaloed_ele = haloed_element.size();
15669 Flat_packed_unsigneds.push_back(nhaloed_ele);
15670 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15671 std::stringstream junk;
15672 junk <<
"Number of haloed elements " << nhaloed_ele;
15673 Flat_packed_unsigneds_string.push_back(junk.str());
15677 for (
unsigned e = 0; e < nhaloed_ele; e++)
15680 FiniteElement* ele_pt = haloed_element[e];
15681 const unsigned nroot_haloed_ele =
15682 this->nroot_haloed_element(iproc);
15686 GeneralisedElement *gen_ele_pt = ele_pt;
15687 const unsigned haloed_ele_index =
15688 this->try_to_add_root_haloed_element_pt(iproc, gen_ele_pt);
15692 if (nroot_haloed_ele == haloed_ele_index)
15694 Flat_packed_unsigneds.push_back(1);
15695 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15696 Flat_packed_unsigneds_string.push_back(
"Haloed element needs to be constructed");
15700 get_required_elemental_information_helper(iproc, ele_pt);
15703 const unsigned nnodes = ele_pt->nnode();
15704 for (
unsigned j = 0; j < nnodes; j++)
15706 Node* node_pt = ele_pt->node_pt(j);
15710 add_haloed_node_helper(iproc, node_pt);
15716 Flat_packed_unsigneds.push_back(0);
15717 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15718 Flat_packed_unsigneds_string.push_back(
"Haloed element already exists");
15720 Flat_packed_unsigneds.push_back(haloed_ele_index);
15721 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15722 Flat_packed_unsigneds_string.push_back(
"Index of existing haloed element");
15736 int send_proc =
static_cast<int>(iproc);
15738 int recv_proc =
static_cast<int>(iproc);
15739 send_and_receive_elements_nodes_info(send_proc, recv_proc);
15748 Counter_for_flat_packed_doubles=0;
15749 Counter_for_flat_packed_unsigneds=0;
15752 for (
unsigned bs = 0; bs < nshared_boundaries_with_iproc; bs++)
15755 const unsigned nhaloed_ele =
15756 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
15758 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15759 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
15760 <<
" Number of elements need to be constructed "
15761 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
15766 for (
unsigned e = 0; e < nhaloed_ele; e++)
15770 create_halo_element(iproc,
15771 iproc_currently_created_nodes_pt[iproc],
15772 other_proc_shd_bnd_node_pt,
15774 node_name_to_global_index,
15775 global_shared_node_pt);
15787 if (Print_timings_level_adaptation>1)
15790 double t_final_regenerate_halo_ed_elements_nodes_first_stage =
15791 TimingHelpers::timer() - t_start_regenerate_halo_ed_elements_nodes_first_stage;
15793 oomph_info <<
"CPU for re-generating halo(ed) elements/nodes "
15794 <<
"(first stage) [n_ele="<< n_ele <<
"]: "
15795 << t_final_regenerate_halo_ed_elements_nodes_first_stage
15812 double t_start_regenerate_halo_ed_elements_nodes_second_stage =
15813 TimingHelpers::timer();
15817 reset_halo_haloed_scheme_helper(other_proc_shd_bnd_node_pt,
15818 iproc_currently_created_nodes_pt,
15820 node_name_to_global_index,
15821 global_shared_node_pt);
15823 if (Print_timings_level_adaptation>1)
15826 double t_final_regenerate_halo_ed_elements_nodes_second_stage =
15827 TimingHelpers::timer() - t_start_regenerate_halo_ed_elements_nodes_second_stage;
15829 oomph_info <<
"CPU for re-generating halo(ed) elements/nodes "
15830 <<
"(second stage) [n_ele="<< n_ele <<
"]: "
15831 << t_final_regenerate_halo_ed_elements_nodes_second_stage
15841 Flat_packed_unsigneds.clear();
15842 Flat_packed_doubles.clear();
15843 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15844 Flat_packed_unsigneds_string.clear();
15849 if (Print_timings_level_adaptation>1)
15851 tt_end = TimingHelpers::timer();
15853 <<
"CPU for resetting halo-haloed scheme (without classification of halo and haloed nodes): "
15854 << tt_end-tt_start << std::endl;
15860 const bool report_stats =
true;
15861 DocInfo tmp_doc_info;
15862 tmp_doc_info.disable_doc();
15865 this->classify_halo_and_haloed_nodes(tmp_doc_info,report_stats);
15869 if (Print_timings_level_adaptation>1)
15871 tt_end = TimingHelpers::timer();
15873 <<
"CPU for resetting halo-haloed scheme (with classification of halo and haloed nodes): "
15874 << tt_end-tt_start << std::endl;
15892 template <
class ELEMENT>
15895 Vector<Vector<Vector<std::map<unsigned, Node*> > > >
15896 &other_proc_shd_bnd_node_pt,
15897 Vector<Vector<Vector<unsigned> > > &global_node_names,
15898 std::map<Vector<unsigned>,
unsigned> &node_name_to_global_index,
15899 Vector<Node*> &global_shared_node_pt)
15902 const unsigned nproc = this->communicator_pt()->nproc();
15904 const unsigned my_rank = this->communicator_pt()->my_rank();
15906 OomphCommunicator* comm_pt = this->communicator_pt();
15916 unsigned counter_nodes = 0;
15918 std::map<Node*, bool> done_node;
15920 std::map<Node*, unsigned> local_node_number;
15922 Vector<Node*> local_node_pt;
15938 Vector<Vector<Vector<unsigned> > > local_node_names;
15941 for (
unsigned iproc = 0; iproc < nproc; iproc++)
15944 if (iproc != my_rank)
15947 const unsigned n_shd_bnds_with_iproc =
15948 this->nshared_boundaries(my_rank, iproc);
15951 Vector<unsigned> bnd_shd_with_iproc =
15952 this->shared_boundaries_ids(my_rank, iproc);
15955 for (
unsigned ishd = 0; ishd < n_shd_bnds_with_iproc; ishd++)
15958 std::map<Node*,bool> done_node_shd_bnd;
15960 unsigned shd_bnd_id = bnd_shd_with_iproc[ishd];
15962 const unsigned n_shd_bnd_ele =
15963 this->nshared_boundary_element(shd_bnd_id);
15966 for (
unsigned e = 0; e < n_shd_bnd_ele; e++)
15969 FiniteElement* ele_pt =
15970 this->shared_boundary_element_pt(shd_bnd_id, e);
15973 const unsigned n_nodes = ele_pt->nnode();
15976 for (
unsigned n = 0; n < n_nodes; n++)
15979 Node* node_pt = ele_pt->node_pt(n);
15984 if (!done_node_shd_bnd[node_pt] &&
15985 this->is_node_on_shared_boundary(shd_bnd_id,
15989 done_node_shd_bnd[node_pt] =
true;
15994 const unsigned n_nodes_shd_bnd =
15995 nsorted_shared_boundary_node(shd_bnd_id);
15998 unsigned index = 0;
16002 bool found_node_on_shared_boundary =
false;
16006 for (
unsigned k = 0; k < n_nodes_shd_bnd; k++)
16009 Node* shd_bnd_node_pt =
16010 sorted_shared_boundary_node_pt(shd_bnd_id, k);
16013 if (shd_bnd_node_pt == node_pt)
16019 found_node_on_shared_boundary =
true;
16028 if (!found_node_on_shared_boundary)
16030 std::ostringstream error_message;
16032 <<
"The index of the node on boundary ("<<shd_bnd_id
16033 <<
") was not found.\n"
16034 <<
"These are the node coordinates\n"
16035 <<
"("<<node_pt->x(0)<<
","<<node_pt->x(1)<<
").\n";
16036 throw OomphLibError(error_message.str(),
16037 OOMPH_CURRENT_FUNCTION,
16038 OOMPH_EXCEPTION_LOCATION);
16043 Vector<unsigned> node_name(5);
16044 node_name[0] = my_rank;
16045 node_name[1] = iproc;
16046 node_name[2] = shd_bnd_id;
16047 node_name[3] = index;
16052 if (!done_node[node_pt])
16057 local_node_pt.push_back(node_pt);
16060 local_node_number[node_pt] = counter_nodes;
16062 node_name[4] = counter_nodes;
16066 done_node[node_pt] =
true;
16070 Vector<Vector<unsigned> > first_node_name(1);
16071 first_node_name[0] = node_name;
16072 local_node_names.push_back(first_node_name);
16079 unsigned node_number = local_node_number[node_pt];
16082 node_name[4] = node_number;
16086 local_node_names[node_number].push_back(node_name);
16112 unsigned n_total_local_names = 0;
16114 const unsigned n_local_nodes = local_node_names.size();
16117 for (
unsigned i = 0; i < n_local_nodes; i++)
16120 const unsigned n_inode_names = local_node_names[i].size();
16122 n_total_local_names+=n_inode_names;
16127 const unsigned n_info_per_node_name = 5;
16129 Vector<unsigned> flat_packed_send_udata(n_total_local_names*n_info_per_node_name);
16131 unsigned counter = 0;
16133 for (
unsigned i = 0; i < n_local_nodes; i++)
16136 const unsigned n_inode_names = local_node_names[i].size();
16138 for (
unsigned j = 0 ; j < n_inode_names; j++)
16141 flat_packed_send_udata[counter++]=local_node_names[i][j][0];
16143 flat_packed_send_udata[counter++]=local_node_names[i][j][1];
16145 flat_packed_send_udata[counter++]=local_node_names[i][j][2];
16147 flat_packed_send_udata[counter++]=local_node_names[i][j][3];
16149 flat_packed_send_udata[counter++]=local_node_names[i][j][4];
16159 const unsigned n_udata_send_to_root = flat_packed_send_udata.size();
16172 const unsigned root_processor = 0;
16176 Vector<unsigned> root_n_names_per_processor(nproc);
16180 MPI_Gather(&n_total_local_names, 1, MPI_UNSIGNED,
16181 &root_n_names_per_processor[0], 1, MPI_UNSIGNED,
16182 root_processor, comm_pt->mpi_comm());
16186 unsigned root_n_total_udata_receive = 0;
16187 Vector<int> root_n_udata_to_receive(nproc,0);
16188 for (
unsigned iproc = 0; iproc < nproc; iproc++)
16190 root_n_udata_to_receive[iproc]=
16191 root_n_names_per_processor[iproc]*n_info_per_node_name;
16192 root_n_total_udata_receive+=root_n_udata_to_receive[iproc];
16197 Vector<int> root_uoffsets_receive(nproc,0);
16198 root_uoffsets_receive[0] = 0;
16199 for (
unsigned iproc = 1; iproc < nproc; iproc++)
16202 root_uoffsets_receive[iproc] =
16203 root_uoffsets_receive[iproc-1] + root_n_udata_to_receive[iproc-1];
16208 if (flat_packed_send_udata.size()==0)
16210 flat_packed_send_udata.resize(1);
16214 Vector<unsigned> root_flat_packed_receive_udata(root_n_total_udata_receive);
16217 if (my_rank!=root_processor)
16220 if (root_flat_packed_receive_udata.size()==0)
16222 root_flat_packed_receive_udata.resize(1);
16227 MPI_Gatherv(&flat_packed_send_udata[0],
16230 n_udata_send_to_root,
16233 &root_flat_packed_receive_udata[0],
16237 &root_n_udata_to_receive[0],
16240 &root_uoffsets_receive[0],
16246 comm_pt->mpi_comm());
16249 flat_packed_send_udata.clear();
16250 flat_packed_send_udata.resize(0);
16258 Vector<unsigned> flat_packed_root_send_receive_udata;
16264 if (my_rank == root_processor)
16270 Vector<Vector<Vector<unsigned> > > root_global_node_names;
16276 Vector<Vector<unsigned> > root_local_node_names;
16279 unsigned rcounter = 0;
16281 for (
unsigned iproc = 0; iproc < nproc; iproc++)
16284 const unsigned n_local_names_iproc =
16285 root_n_names_per_processor[iproc];
16286 for (
unsigned i = 0; i < n_local_names_iproc; i++)
16289 Vector<unsigned> node_name(n_info_per_node_name);
16290 for (
unsigned j = 0; j < n_info_per_node_name; j++)
16291 {node_name[j] = root_flat_packed_receive_udata[rcounter++];}
16294 root_local_node_names.push_back(node_name);
16301 const unsigned n_root_local_node_names =
16302 root_local_node_names.size();
16314 Vector<unsigned> node_name_counter_part(n_root_local_node_names);
16317 std::map<Vector<unsigned>,
bool> done_name;
16321 for (
unsigned i = 0; i < n_root_local_node_names; i++)
16324 Vector<unsigned> node_name = root_local_node_names[i];
16327 if (!done_name[node_name])
16330 done_name[node_name] =
true;
16334 bool found_both_names_node =
false;
16339 for (
unsigned j = i+1; j < n_root_local_node_names; j++)
16341 Vector<unsigned> node_name_r = root_local_node_names[j];
16344 if (!done_name[node_name_r])
16348 if (node_name[0] == node_name_r[1] &&
16349 node_name[1] == node_name_r[0] &&
16350 node_name[2] == node_name_r[2] &&
16351 node_name[3] == node_name_r[3])
16354 done_name[node_name_r] =
true;
16357 node_name_counter_part[i] = j;
16360 node_name_counter_part[j] = i;
16363 found_both_names_node =
true;
16375 if (!found_both_names_node)
16377 std::ostringstream error_message;
16379 <<
"The counter-part of the current name node was "
16380 <<
"not found,\nthe current node name is:\n"
16381 <<
"iproc:("<<node_name[0]<<
")\n"
16382 <<
"jproc:("<<node_name[1]<<
")\n"
16383 <<
"ishd_bnd:("<<node_name[2]<<
")\n"
16384 <<
"index:("<<node_name[3]<<
")\n";
16385 throw OomphLibError(error_message.str(),
16386 OOMPH_CURRENT_FUNCTION,
16387 OOMPH_EXCEPTION_LOCATION);
16403 for (
unsigned i = 0; i < n_root_local_node_names; i++)
16406 Vector<unsigned> node_name = root_local_node_names[i];
16409 if (!done_name[node_name])
16412 Vector<Vector<unsigned> > all_node_names;
16415 all_node_names.push_back(node_name);
16418 unsigned idx_c = node_name_counter_part[i];
16420 Vector<unsigned> node_name_r = root_local_node_names[idx_c];
16423 all_node_names.push_back(node_name_r);
16429 unsigned n_current_names = all_node_names.size();
16432 unsigned icounter = 0;
16435 while(icounter < n_current_names)
16438 Vector<unsigned> current_node_name = all_node_names[icounter];
16443 if (!done_name[current_node_name])
16446 done_name[current_node_name] =
true;
16451 for (
unsigned j=i+1;j<n_root_local_node_names;j++)
16454 Vector<unsigned> other_node_name = root_local_node_names[j];
16457 if (!done_name[other_node_name])
16460 if ((current_node_name[0] == other_node_name[0]) &&
16461 (current_node_name[4] == other_node_name[4]))
16466 done_name[other_node_name] =
true;
16469 Vector<Vector<unsigned> >::iterator it
16470 = std::find(all_node_names.begin(),
16471 all_node_names.end(),
16473 if (it==all_node_names.end())
16475 all_node_names.push_back(other_node_name);
16477 unsigned k = node_name_counter_part[j];
16479 Vector<unsigned> other_node_name_r =
16480 root_local_node_names[k];
16484 if (!done_name[other_node_name_r])
16486 all_node_names.push_back(other_node_name_r);
16501 n_current_names = all_node_names.size();
16509 root_global_node_names.push_back(all_node_names);
16522 flat_packed_root_send_receive_udata.clear();
16524 const unsigned n_global_nodes = root_global_node_names.size();
16527 flat_packed_root_send_receive_udata.push_back(n_global_nodes);
16530 for (
unsigned i = 0; i < n_global_nodes; i++)
16533 Vector<Vector<unsigned> > global_inode_names =
16534 root_global_node_names[i];
16536 const unsigned n_names_global_inode = global_inode_names.size();
16539 flat_packed_root_send_receive_udata.push_back(n_names_global_inode);
16541 for (
unsigned j = 0; j < n_names_global_inode; j++)
16544 for (
unsigned k = 0; k < n_info_per_node_name; k++)
16548 flat_packed_root_send_receive_udata.
16549 push_back(global_inode_names[j][k]);
16570 unsigned root_n_udata_sent_to_all_proc =
16571 flat_packed_root_send_receive_udata.size();
16573 MPI_Bcast(&root_n_udata_sent_to_all_proc,
16575 1, MPI_UNSIGNED, root_processor,
16576 comm_pt->mpi_comm());
16579 if (my_rank != root_processor)
16581 flat_packed_root_send_receive_udata.
16582 resize(root_n_udata_sent_to_all_proc);
16586 MPI_Bcast(&flat_packed_root_send_receive_udata[0],
16590 root_n_udata_sent_to_all_proc,
16595 comm_pt->mpi_comm());
16600 const unsigned n_global_nodes =
16601 flat_packed_root_send_receive_udata[counter++];
16608 global_node_names.resize(n_global_nodes);
16610 unsigned n_read_global_nodes = 0;
16611 while (n_read_global_nodes < n_global_nodes)
16614 const unsigned n_names_global_inode =
16615 flat_packed_root_send_receive_udata[counter++];
16617 const unsigned i = n_read_global_nodes;
16619 global_node_names[i].resize(n_names_global_inode);
16621 for (
unsigned j = 0; j < n_names_global_inode; j++)
16624 global_node_names[i][j].resize(n_info_per_node_name);
16627 for (
unsigned k = 0; k < n_info_per_node_name; k++)
16631 global_node_names[i][j][k] =
16632 flat_packed_root_send_receive_udata[counter++];
16638 Vector<unsigned> node_name(n_info_per_node_name-1);
16639 node_name[0] = global_node_names[i][j][0];
16640 node_name[1] = global_node_names[i][j][1];
16641 node_name[2] = global_node_names[i][j][2];
16642 node_name[3] = global_node_names[i][j][3];
16647 node_name_to_global_index[node_name] = i;
16652 n_read_global_nodes++;
16658 if (counter != root_n_udata_sent_to_all_proc)
16660 std::ostringstream error_stream;
16662 <<
"The info. received from root regarding the global names of "
16663 <<
"the nodes\nwas not completely read.\n"
16664 <<
"The number of data sent/received from root is: ("
16665 <<root_n_udata_sent_to_all_proc<<
")\n"
16666 <<
"The number of data read from the received info. is: ("
16667 <<counter<<
")\n\n";
16668 throw OomphLibError(error_stream.str(),
16669 OOMPH_CURRENT_FUNCTION,
16670 OOMPH_EXCEPTION_LOCATION);
16688 global_shared_node_pt.resize(n_global_nodes, 0);
16691 for (
unsigned i = 0; i < n_global_nodes; i++)
16695 bool is_this_a_local_node_name =
false;
16696 unsigned local_node_number;
16698 const unsigned n_names_global_inode = global_node_names[i].size();
16700 for (
unsigned j = 0; j < n_names_global_inode; j++)
16703 const unsigned iproc = global_node_names[i][j][0];
16704 local_node_number = global_node_names[i][j][4];
16707 if (my_rank == iproc)
16710 is_this_a_local_node_name =
true;
16719 if (is_this_a_local_node_name)
16724 const unsigned n_names_local_node =
16725 local_node_names[local_node_number].size();
16726 unsigned n_names_found_on_global_name_node = 0;
16731 global_shared_node_pt[i] = local_node_pt[local_node_number];
16737 for (
unsigned j = 0; j < n_names_global_inode; j++)
16740 const unsigned iproc = global_node_names[i][j][0];
16743 if (iproc != my_rank)
16746 local_node_names[local_node_number].
16747 push_back(global_node_names[i][j]);
16752 const unsigned jproc = global_node_names[i][j][1];
16753 const unsigned ishd_bnd = global_node_names[i][j][2];
16754 const unsigned idx = global_node_names[i][j][3];
16755 const unsigned n_local_node = global_node_names[i][j][4];
16757 for (
unsigned k = 0; k < n_names_local_node; k++)
16759 if ((local_node_names[local_node_number][k][0] == iproc) &&
16760 (local_node_names[local_node_number][k][1] == jproc) &&
16761 (local_node_names[local_node_number][k][2] == ishd_bnd) &&
16762 (local_node_names[local_node_number][k][3] == idx) &&
16763 (local_node_names[local_node_number][k][4] == n_local_node))
16767 n_names_found_on_global_name_node++;
16781 if (n_names_local_node != n_names_found_on_global_name_node)
16783 std::ostringstream error_stream;
16785 <<
"The local node names corresponding to the local "
16786 <<
"node ("<< local_node_number <<
") were\n"
16787 <<
"not found on the global node names.\n\n"
16788 <<
"These are the names of the local node\n"
16789 <<
"Name k: iproc, jproc, ishd_bnd, idx. #node\n";
16790 for (
unsigned k = 0; k < n_names_local_node; k++)
16792 error_stream<<
"Name("<<k<<
"): "
16793 <<local_node_names[local_node_number][k][0]
16794 <<
", "<<local_node_names[local_node_number][k][1]
16795 <<
", "<<local_node_names[local_node_number][k][2]
16796 <<
", "<<local_node_names[local_node_number][k][3]
16797 <<
", "<<local_node_names[local_node_number][k][4]
16802 <<
"\n\nThese are the names of the global node\n"
16803 <<
"Name k: iproc, jproc, ishd_bnd, idx. #node\n";
16804 for (
unsigned k = 0; k < n_names_global_inode; k++)
16806 error_stream<<
"Name("<<k<<
"): "
16807 <<global_node_names[i][k][0] <<
", "
16808 <<global_node_names[i][k][1] <<
", "
16809 <<global_node_names[i][k][2] <<
", "
16810 <<global_node_names[i][k][3] <<
", "
16811 <<global_node_names[i][k][4] <<
"\n";
16814 throw OomphLibError(error_stream.str(),
16815 OOMPH_CURRENT_FUNCTION,
16816 OOMPH_EXCEPTION_LOCATION);
16842 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
16845 for (
unsigned i = 0 ; i < n_local_nodes; i++)
16848 const unsigned n_names = local_node_names[i].size();
16852 Node* node_pt = local_node_pt[i];
16855 for (
unsigned j = 0; j < n_names; j++)
16858 const unsigned iproc = local_node_names[i][j][0];
16859 const unsigned jproc = local_node_names[i][j][1];
16860 const unsigned ishd_bnd =
16861 local_node_names[i][j][2] - initial_shd_bnd_id;
16862 const unsigned index = local_node_names[i][j][3];
16869 other_proc_shd_bnd_node_pt[iproc][jproc][ishd_bnd][index]=node_pt;
16873 other_proc_shd_bnd_node_pt[jproc][iproc][ishd_bnd][index]=node_pt;
16892 template <
class ELEMENT>
16895 Vector<Vector<Vector<unsigned> > > &global_node_names,
16896 std::map<Vector<unsigned>,
unsigned> &node_name_to_global_index,
16897 Vector<Node*> &global_shared_node_pt)
16900 const unsigned nproc = this->communicator_pt()->nproc();
16901 const unsigned my_rank = this->communicator_pt()->my_rank();
16904 const unsigned n_nodes_on_shd_bnds = global_node_names.size();
16911 Vector<std::set<Node*> > node_on_shd_bnd_pt(nproc);
16915 std::map<Node*, unsigned> node_pt_to_global_shd_bnd_index;
16919 for (
unsigned i = 0; i < n_nodes_on_shd_bnds; i++)
16923 const unsigned n_names = global_node_names[i].size();
16925 for (
unsigned j = 0; j < n_names; j++)
16928 Vector<unsigned> node_name(4);
16929 node_name[0] = global_node_names[i][j][0];
16930 node_name[1] = global_node_names[i][j][1];
16931 node_name[2] = global_node_names[i][j][2];
16932 node_name[3] = global_node_names[i][j][3];
16935 if (node_name[0]==my_rank)
16938 const unsigned jproc = node_name[1];
16941 std::map<Vector<unsigned>,
unsigned>::iterator it =
16942 node_name_to_global_index.find(node_name);
16943 if (it!=node_name_to_global_index.end())
16947 if (i!=(*it).second)
16949 std::ostringstream error_message;
16951 <<
"The global node number "<<(*it).second
16952 <<
") obtained from the current node\n"
16953 <<
"name is not the same as the current node number ("
16956 <<
"iproc:"<<node_name[0]<<
"\n"
16957 <<
"jproc:"<<node_name[1]<<
"\n"
16958 <<
"shd_bnd_id:"<<node_name[2]<<
"\n"
16959 <<
"index:"<<node_name[3]<<
"\n\n";
16960 throw OomphLibError(error_message.str(),
16961 OOMPH_CURRENT_FUNCTION,
16962 OOMPH_EXCEPTION_LOCATION);
16968 std::ostringstream error_message;
16970 <<
"The node name is not registerd as living in this processor.\n"
16972 <<
"iproc:"<<node_name[0]<<
"\n"
16973 <<
"jproc:"<<node_name[1]<<
"\n"
16974 <<
"shd_bnd_id:"<<node_name[2]<<
"\n"
16975 <<
"index:"<<node_name[3]<<
"\n\n";
16976 throw OomphLibError(error_message.str(),
16977 OOMPH_CURRENT_FUNCTION,
16978 OOMPH_EXCEPTION_LOCATION);
16981 #endif // #ifdef PARANOID
16984 Node* node_pt = global_shared_node_pt[i];
16989 std::ostringstream error_message;
16991 <<
"There is not global shared node within this\n"
16992 <<
"global node number ("<<i<<
"). The global shared\n"
16993 <<
"node pointer is null\n\n";
16994 throw OomphLibError(error_message.str(),
16995 OOMPH_CURRENT_FUNCTION,
16996 OOMPH_EXCEPTION_LOCATION);
16998 #endif // #ifdef PARANOID
17002 node_on_shd_bnd_pt[jproc].insert(node_pt);
17005 node_pt_to_global_shd_bnd_index[node_pt] = i;
17008 else if (node_name[1]==my_rank)
17011 const unsigned jproc = node_name[0];
17014 std::map<Vector<unsigned>,
unsigned>::iterator it =
17015 node_name_to_global_index.find(node_name);
17016 if (it!=node_name_to_global_index.end())
17020 if (i!=(*it).second)
17022 std::ostringstream error_message;
17024 <<
"The global node number "<<(*it).second
17025 <<
") obtained from the current node\n"
17026 <<
"name is not the same as the current node number ("
17029 <<
"iproc:"<<node_name[0]<<
"\n"
17030 <<
"jproc:"<<node_name[1]<<
"\n"
17031 <<
"shd_bnd_id:"<<node_name[2]<<
"\n"
17032 <<
"index:"<<node_name[3]<<
"\n\n";
17033 throw OomphLibError(error_message.str(),
17034 OOMPH_CURRENT_FUNCTION,
17035 OOMPH_EXCEPTION_LOCATION);
17041 std::ostringstream error_message;
17043 <<
"The node name is not registerd as living in this processor.\n"
17045 <<
"iproc:"<<node_name[0]<<
"\n"
17046 <<
"jproc:"<<node_name[1]<<
"\n"
17047 <<
"shd_bnd_id:"<<node_name[2]<<
"\n"
17048 <<
"index:"<<node_name[3]<<
"\n\n";
17049 throw OomphLibError(error_message.str(),
17050 OOMPH_CURRENT_FUNCTION,
17051 OOMPH_EXCEPTION_LOCATION);
17054 #endif // #ifdef PARANOID
17057 Node* node_pt = global_shared_node_pt[i];
17062 std::ostringstream error_message;
17064 <<
"There is not global shared node within this\n"
17065 <<
"global node number ("<<i<<
"). The global shared\n"
17066 <<
"node pointer is null\n\n";
17067 throw OomphLibError(error_message.str(),
17068 OOMPH_CURRENT_FUNCTION,
17069 OOMPH_EXCEPTION_LOCATION);
17071 #endif // #ifdef PARANOID
17075 node_on_shd_bnd_pt[jproc].insert(node_pt);
17078 node_pt_to_global_shd_bnd_index[node_pt] = i;
17096 Vector<Vector<unsigned> > global_node_on_shared_bound(nproc);
17099 Vector<Vector<Vector<unsigned> > > global_node_original_boundaries(nproc);
17102 Vector<Vector<Vector<double> > > global_node_zeta_coordinate(nproc);
17105 for (
unsigned iproc = 0; iproc < nproc; iproc++)
17108 std::set<Node*> nodes_shared_pt = node_on_shd_bnd_pt[iproc];
17111 for (std::set<Node*>::iterator it = nodes_shared_pt.begin();
17112 it!=nodes_shared_pt.end(); it++)
17115 Node* node_pt = (*it);
17117 Vector<unsigned> on_original_boundaries;
17120 Vector<double> zeta_coordinate;
17122 const unsigned n_bnd=this->initial_shared_boundary_id();
17125 for (
unsigned bb = 0; bb < n_bnd; bb++)
17128 if (node_pt->is_on_boundary(bb))
17131 on_original_boundaries.push_back(bb);
17133 Vector<double> zeta(1);
17134 node_pt->get_coordinates_on_boundary(bb, zeta);
17136 zeta_coordinate.push_back(zeta[0]);
17142 if (on_original_boundaries.size()>0)
17145 std::map<Node*,unsigned>::iterator it_index =
17146 node_pt_to_global_shd_bnd_index.find(node_pt);
17148 if (it_index==node_pt_to_global_shd_bnd_index.end())
17150 std::ostringstream error_message;
17152 <<
"We could not find the global shared node index associated\n"
17153 <<
"with the node pointer with vertices coordinates:\n"
17154 <<
"("<<node_pt->x(0)<<
", "<<node_pt->x(1)<<
")\n\n";
17155 throw OomphLibError(error_message.str(),
17156 OOMPH_CURRENT_FUNCTION,
17157 OOMPH_EXCEPTION_LOCATION);
17161 const unsigned global_shared_node_number = (*it_index).second;
17163 global_node_on_shared_bound[iproc].push_back(global_shared_node_number);
17165 global_node_original_boundaries[iproc].
17166 push_back(on_original_boundaries);
17168 global_node_zeta_coordinate[iproc].push_back(zeta_coordinate);
17188 OomphCommunicator* comm_pt = this->communicator_pt();
17192 MPI_Request request;
17195 for (
unsigned iproc = 0; iproc < nproc; iproc++)
17198 const unsigned n_shd_nodes_my_rank_iproc =
17199 node_on_shd_bnd_pt[iproc].size();
17203 if (n_shd_nodes_my_rank_iproc > 0 && iproc != my_rank)
17206 Vector<unsigned> flat_package_unsigned_send;
17209 flat_package_unsigned_send.push_back(n_shd_nodes_my_rank_iproc);
17212 const unsigned n_global_shared_node_on_original_boundary =
17213 global_node_on_shared_bound[iproc].size();
17217 flat_package_unsigned_send.
17218 push_back(n_global_shared_node_on_original_boundary);
17222 Vector<double> flat_package_double_send;
17225 for (
unsigned i = 0; i < n_global_shared_node_on_original_boundary; i++)
17228 const unsigned global_shared_node_index =
17229 global_node_on_shared_bound[iproc][i];
17233 flat_package_unsigned_send.push_back(global_shared_node_index);
17236 Vector<unsigned> on_original_boundaries =
17237 global_node_original_boundaries[iproc][i];
17240 Vector<double> zeta_coordinate =
17241 global_node_zeta_coordinate[iproc][i];
17245 const unsigned n_original_boundaries =
17246 on_original_boundaries.size();
17250 flat_package_unsigned_send.push_back(n_original_boundaries);
17254 for (
unsigned j = 0; j < n_original_boundaries; j++)
17258 flat_package_unsigned_send.push_back(on_original_boundaries[j]);
17260 flat_package_double_send.push_back(zeta_coordinate[j]);
17268 const unsigned n_udata_send = flat_package_unsigned_send.size();
17269 int n_udata_send_int = n_udata_send;
17272 MPI_Isend(&n_udata_send_int,1,MPI_UNSIGNED,
17273 iproc,1,comm_pt->mpi_comm(), &request);
17275 int n_udata_received_int = 0;
17276 MPI_Recv(&n_udata_received_int,1,MPI_UNSIGNED,
17277 iproc,1,comm_pt->mpi_comm(),&status);
17278 MPI_Wait(&request,MPI_STATUS_IGNORE);
17280 if (n_udata_send!=0)
17282 MPI_Isend(&flat_package_unsigned_send[0],
17283 n_udata_send,MPI_UNSIGNED,
17284 iproc,2,comm_pt->mpi_comm(),&request);
17287 const unsigned n_udata_received =
17288 static_cast<unsigned>(n_udata_received_int);
17291 Vector<unsigned> flat_package_unsigned_receive(n_udata_received);
17293 if (n_udata_received!=0)
17295 MPI_Recv(&flat_package_unsigned_receive[0],
17296 n_udata_received,MPI_UNSIGNED,
17297 iproc,2,comm_pt->mpi_comm(),&status);
17300 if (n_udata_send!=0)
17302 MPI_Wait(&request,MPI_STATUS_IGNORE);
17308 const unsigned n_ddata_send = flat_package_double_send.size();
17309 int n_ddata_send_int = n_ddata_send;
17312 MPI_Isend(&n_ddata_send_int,1,MPI_UNSIGNED,
17313 iproc,1,comm_pt->mpi_comm(), &request);
17315 int n_ddata_received_int = 0;
17316 MPI_Recv(&n_ddata_received_int,1,MPI_UNSIGNED,
17317 iproc,1,comm_pt->mpi_comm(),&status);
17318 MPI_Wait(&request,MPI_STATUS_IGNORE);
17320 if (n_ddata_send!=0)
17322 MPI_Isend(&flat_package_double_send[0],
17323 n_ddata_send,MPI_DOUBLE,
17324 iproc,2,comm_pt->mpi_comm(),&request);
17327 const unsigned n_ddata_received =
17328 static_cast<unsigned>(n_ddata_received_int);
17331 Vector<double> flat_package_double_receive(n_ddata_received);
17333 if (n_ddata_received!=0)
17335 MPI_Recv(&flat_package_double_receive[0],
17336 n_ddata_received,MPI_DOUBLE,
17337 iproc,2,comm_pt->mpi_comm(),&status);
17340 if (n_ddata_send!=0)
17342 MPI_Wait(&request,MPI_STATUS_IGNORE);
17350 unsigned n_shared_nodes_received = flat_package_unsigned_receive[0];
17354 n_shared_nodes_received++;
17355 n_shared_nodes_received--;
17358 if (n_shd_nodes_my_rank_iproc != n_shared_nodes_received)
17360 std::ostringstream error_message;
17362 <<
"The number of shared nodes between the pair of processors is\n"
17364 <<
"N.shared nodes proc ("<<my_rank<<
") with proc ("<<iproc<<
"): ("
17365 <<n_shd_nodes_my_rank_iproc<<
"\n"
17366 <<
"N.shared nodes proc ("<<iproc<<
") with proc ("<<my_rank<<
"): ("
17367 <<n_shared_nodes_received<<
"\n\n"
17368 <<
"You should have got the same error in proc: ("<<iproc<<
")\n\n";
17369 throw OomphLibError(error_message.str(),
17370 OOMPH_CURRENT_FUNCTION,
17371 OOMPH_EXCEPTION_LOCATION);
17384 unsigned current_index_data = 2;
17385 unsigned current_index_ddata = 0;
17386 while(current_index_data < n_udata_received)
17389 const unsigned global_shared_node_index =
17390 flat_package_unsigned_receive[current_index_data++];
17397 const unsigned n_original_boundaries =
17398 flat_package_unsigned_receive[current_index_data++];
17401 node_pt = global_shared_node_pt[global_shared_node_index];
17405 std::ostringstream error_message;
17407 <<
"The global shared node ("<<global_shared_node_index<<
") "
17408 <<
"could not be found in this processor!!!\n"
17409 <<
"However, it was found in processor ("<<iproc<<
"). The "
17410 <<
"data may be no synchronised,\ntherefore "
17411 <<
"we may be looking for a global shared node number that "
17412 <<
"do not\ncorrespond with the one that was sent by "
17413 <<
"processor ("<<iproc<<
")\n\n";
17414 throw OomphLibError(error_message.str(),
17415 OOMPH_CURRENT_FUNCTION,
17416 OOMPH_EXCEPTION_LOCATION);
17418 #endif // #ifdef PARANOID
17422 for (
unsigned i = 0; i < n_original_boundaries; i++)
17426 const unsigned original_bound_id =
17427 flat_package_unsigned_receive[current_index_data++];
17430 this->add_boundary_node(original_bound_id, node_pt);
17433 Vector<double> zeta(1);
17434 zeta[0] = flat_package_double_receive[current_index_ddata++];
17435 node_pt->set_coordinates_on_boundary(original_bound_id, zeta);
17458 template <
class ELEMENT>
17460 Vector<Vector<Vector<std::map<unsigned, Node*> > > >
17461 &other_proc_shd_bnd_node_pt,
17462 Vector<Vector<Node *> > &iproc_currently_created_nodes_pt,
17463 Vector<Vector<Vector<unsigned> > > &global_node_names,
17464 std::map<Vector<unsigned>,
unsigned> &node_name_to_global_index,
17465 Vector<Node*> &global_shared_node_pt)
17468 const unsigned nproc = this->communicator_pt()->nproc();
17469 const unsigned my_rank = this->communicator_pt()->my_rank();
17477 std::map<Node*, bool> is_global_shared_node;
17478 std::map<Node*, unsigned> global_shared_node_index;
17481 const unsigned n_global_shared_nodes = global_shared_node_pt.size();
17483 for (
unsigned i = 0; i < n_global_shared_nodes; i++)
17486 Node* node_pt = global_shared_node_pt[i];
17488 is_global_shared_node[node_pt] =
true;
17490 global_shared_node_index[node_pt] = i;
17510 Vector<std::set<GeneralisedElement*> > additional_elements_pt(nproc);
17513 for (
unsigned iproc = 0; iproc < nproc; iproc++)
17515 if (iproc!=my_rank)
17518 Vector<GeneralisedElement*> haloed_ele_pt =
17519 this->root_haloed_element_pt(iproc);
17522 const unsigned n_haloed_ele =
17523 this->nroot_haloed_element(iproc);
17526 for (
unsigned ihd = 0; ihd < n_haloed_ele; ihd++)
17529 GeneralisedElement* gele_pt = haloed_ele_pt[ihd];
17531 FiniteElement* ele_pt =
dynamic_cast<FiniteElement*
>(gele_pt);
17533 const unsigned n_nodes = ele_pt->nnode();
17535 for (
unsigned n = 0; n < n_nodes; n++)
17538 Node* node_pt = ele_pt->node_pt(n);
17540 if (is_global_shared_node[node_pt])
17543 const unsigned global_index = global_shared_node_index[node_pt];
17545 Vector<Vector<unsigned> > iglobal_names =
17546 global_node_names[global_index];
17549 const unsigned n_names = iglobal_names.size();
17553 for (
unsigned j = 0; j < n_names; j++)
17557 const unsigned proc1 = iglobal_names[j][0];
17558 const unsigned proc2 = iglobal_names[j][1];
17561 additional_elements_pt[proc1].insert(gele_pt);
17562 additional_elements_pt[proc2].insert(gele_pt);
17582 Vector<Vector<FiniteElement*> > send_haloed_ele_pt(nproc);
17585 for (
unsigned iproc = 0; iproc < nproc; iproc++)
17587 if (iproc!=my_rank)
17591 std::set<GeneralisedElement*> iproc_ele_pt =
17592 additional_elements_pt[iproc];
17595 for (std::set<GeneralisedElement*>::iterator it =
17596 iproc_ele_pt.begin(); it!=iproc_ele_pt.end(); it++)
17599 GeneralisedElement* gele_pt = (*it);
17602 Vector<GeneralisedElement*> haloed_ele_pt =
17603 this->root_haloed_element_pt(iproc);
17606 const unsigned n_haloed_ele = this->nroot_haloed_element(iproc);
17610 bool send_ele_to_iproc_processor =
true;
17615 for (
unsigned ihd = 0; ihd < n_haloed_ele; ihd++)
17618 GeneralisedElement* ghd_ele_pt = haloed_ele_pt[ihd];
17619 if (gele_pt == ghd_ele_pt)
17622 send_ele_to_iproc_processor =
false;
17631 if (send_ele_to_iproc_processor)
17634 FiniteElement* ele_pt =
dynamic_cast<FiniteElement*
>(gele_pt);
17637 send_haloed_ele_pt[iproc].push_back(ele_pt);
17659 for (
unsigned iproc = 0; iproc < nproc; iproc++)
17662 if (iproc != my_rank)
17665 const unsigned n_additional_haloed_ele =
17666 send_haloed_ele_pt[iproc].size();
17669 Flat_packed_unsigneds.clear();
17670 Flat_packed_doubles.clear();
17671 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17672 Flat_packed_unsigneds_string.clear();
17678 Flat_packed_unsigneds.push_back(n_additional_haloed_ele);
17679 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17680 std::stringstream junk;
17681 junk <<
"Number of haloed elements " << nhaloed_ele;
17682 Flat_packed_unsigneds_string.push_back(junk.str());
17686 for (
unsigned e = 0; e < n_additional_haloed_ele; e++)
17689 FiniteElement* ele_pt = send_haloed_ele_pt[iproc][e];
17690 const unsigned nroot_haloed_ele =
17691 this->nroot_haloed_element(iproc);
17697 GeneralisedElement *gen_ele_pt = ele_pt;
17699 const unsigned haloed_ele_index =
17700 this->try_to_add_root_haloed_element_pt(iproc, gen_ele_pt);
17704 if (nroot_haloed_ele == haloed_ele_index)
17706 Flat_packed_unsigneds.push_back(1);
17707 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17708 Flat_packed_unsigneds_string.push_back(
"Haloed element needs to be constructed");
17712 get_required_elemental_information_helper(iproc, ele_pt);
17715 const unsigned nnodes = ele_pt->nnode();
17716 for (
unsigned j = 0; j < nnodes; j++)
17718 Node* node_pt = ele_pt->node_pt(j);
17722 add_haloed_node_helper(iproc, node_pt);
17729 Flat_packed_unsigneds.push_back(0);
17730 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17731 Flat_packed_unsigneds_string.push_back(
"Haloed element already exists");
17733 Flat_packed_unsigneds.push_back(haloed_ele_index);
17734 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17735 Flat_packed_unsigneds_string.push_back(
"Index of existing haloed element");
17745 int send_proc =
static_cast<int>(iproc);
17747 int recv_proc =
static_cast<int>(iproc);
17748 send_and_receive_elements_nodes_info(send_proc, recv_proc);
17751 Counter_for_flat_packed_doubles=0;
17752 Counter_for_flat_packed_unsigneds=0;
17755 const unsigned n_additional_halo_ele =
17756 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
17758 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17759 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
17760 <<
" Number of elements need to be constructed "
17761 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
17766 for (
unsigned e = 0; e < n_additional_halo_ele; e++)
17770 create_halo_element(iproc,
17771 iproc_currently_created_nodes_pt[iproc],
17772 other_proc_shd_bnd_node_pt,
17774 node_name_to_global_index,
17775 global_shared_node_pt);
17794 template<
class ELEMENT>
17797 FiniteElement* ele_pt)
17800 const unsigned nbound = this->initial_shared_boundary_id();
17805 Vector<unsigned> associated_boundaries;
17806 Vector<unsigned> face_index_on_boundary;
17808 unsigned counter_face_indexes = 0;
17810 for (
unsigned b = 0; b < nbound; b++)
17813 const unsigned nboundary_ele = nboundary_element(b);
17814 for (
unsigned e = 0; e < nboundary_ele; e++)
17816 if (ele_pt == this->boundary_element_pt(b,e))
17819 associated_boundaries.push_back(b);
17821 face_index_on_boundary.push_back(face_index_at_boundary(b,e));
17822 counter_face_indexes++;
17824 if (counter_face_indexes > 2)
17826 std::stringstream error_message;
17828 <<
"A triangular element can not have more than two of its faces "
17829 <<
"on a boundary!!!\n\n";
17830 throw OomphLibError(error_message.str(),
17831 OOMPH_CURRENT_FUNCTION,
17832 OOMPH_EXCEPTION_LOCATION);
17836 if (counter_face_indexes==2) {
break;}
17837 #endif // #ifdef PARANOID
17847 const unsigned nassociated_boundaries = associated_boundaries.size();
17848 if (nassociated_boundaries > 0)
17850 Flat_packed_unsigneds.push_back(1);
17851 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17852 Flat_packed_unsigneds_string.push_back(
"The element is a boundary element");
17854 Flat_packed_unsigneds.push_back(nassociated_boundaries);
17855 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17856 std::stringstream junk;
17857 junk <<
"The elements is associated to " << nassociated_boundaries <<
" boundaries";
17858 Flat_packed_unsigneds_string.push_back(junk.str());
17865 for (
unsigned i = 0; i < nassociated_boundaries; i++)
17867 unsigned b = associated_boundaries[i];
17868 Flat_packed_unsigneds.push_back(b);
17869 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17870 std::stringstream junk;
17871 junk <<
"Element associated to boundary " << b <<
" of " << nassociated_boundaries <<
" total associated boundaries";
17872 Flat_packed_unsigneds_string.push_back(junk.str());
17874 unsigned f = face_index_on_boundary[i];
17875 Flat_packed_unsigneds.push_back(f);
17876 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17877 std::stringstream junk2;
17878 junk2 <<
"Face index " << f <<
" for associated boundary " << b;
17879 Flat_packed_unsigneds_string.push_back(junk2.str());
17889 Vector<Vector<unsigned> > associated_boundaries_and_regions;
17890 Vector<unsigned> face_index_on_boundary_and_region;
17893 const unsigned n_regions = this->nregion();
17898 unsigned counter_face_indexes_in_regions = 0;
17900 for (
unsigned b = 0; b < nbound; b++)
17903 for (
unsigned i_reg = 0 ; i_reg < n_regions; i_reg++)
17906 const unsigned region_id =
17907 static_cast<unsigned>(this->Region_attribute[i_reg]);
17912 const unsigned nele_in_region =
17913 this->nboundary_element_in_region(b, region_id);
17914 for (
unsigned ee = 0; ee < nele_in_region; ee++)
17919 this->boundary_element_in_region_pt(b, region_id, ee))
17923 Vector<unsigned> bound_and_region(2);
17926 bound_and_region[0] = b;
17928 bound_and_region[1] = region_id;
17931 associated_boundaries_and_regions.push_back(bound_and_region);
17933 face_index_on_boundary_and_region.push_back(
17934 this->face_index_at_boundary_in_region(b,region_id,ee));
17938 counter_face_indexes_in_regions++;
17941 if (counter_face_indexes_in_regions > 2)
17943 std::stringstream error_message;
17945 <<
"A triangular element can not have more than two of its\n"
17946 <<
"faces on a boundary!!!\n\n";
17947 throw OomphLibError(error_message.str(),
17948 OOMPH_CURRENT_FUNCTION,
17949 OOMPH_EXCEPTION_LOCATION);
17964 const unsigned nassociated_boundaries_and_regions =
17965 associated_boundaries_and_regions.size();
17966 if (nassociated_boundaries_and_regions > 0)
17968 Flat_packed_unsigneds.push_back(1);
17969 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17970 Flat_packed_unsigneds_string.push_back(
"The element is associated to boundaries and regions");
17973 Flat_packed_unsigneds.push_back(nassociated_boundaries_and_regions);
17974 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17975 std::stringstream junk;
17976 junk <<
"The element is associated to " << nassociated_boundaries_and_regions <<
" boundaries-regions";
17977 Flat_packed_unsigneds_string.push_back(junk.str());
17984 for (
unsigned i = 0; i < nassociated_boundaries_and_regions; i++)
17986 const unsigned b = associated_boundaries_and_regions[i][0];
17987 Flat_packed_unsigneds.push_back(b);
17988 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17989 std::stringstream junk;
17990 junk <<
"Element associated to boundary " << b <<
" of " << nassociated_boundaries_and_regions <<
" total associated boundaries-regions";
17991 Flat_packed_unsigneds_string.push_back(junk.str());
17994 const unsigned r = associated_boundaries_and_regions[i][1];
17995 Flat_packed_unsigneds.push_back(r);
17996 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17997 std::stringstream junk2;
17998 junk2 <<
"Element associated to region " << r <<
" of " << nassociated_boundaries_and_regions <<
" total associated boundaries-regions";
17999 Flat_packed_unsigneds_string.push_back(junk2.str());
18002 const unsigned f = face_index_on_boundary_and_region[i];
18003 Flat_packed_unsigneds.push_back(f);
18004 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18005 std::stringstream junk3;
18006 junk3 <<
"Face index " << f <<
" for associated boundary-region (" << b <<
"-" << r <<
")";
18007 Flat_packed_unsigneds_string.push_back(junk3.str());
18013 Flat_packed_unsigneds.push_back(0);
18014 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18015 Flat_packed_unsigneds_string.push_back(
"The element is NOT associated to boundaries and regions");
18022 Flat_packed_unsigneds.push_back(0);
18023 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18024 Flat_packed_unsigneds_string.push_back(
"The element is not associated to any original boundary");
18033 Vector<unsigned> associated_shared_boundaries;
18034 Vector<unsigned> face_index_on_shared_boundary;
18037 Vector<unsigned> my_rank_shared_boundaries_ids;
18038 this->shared_boundaries_in_this_processor(my_rank_shared_boundaries_ids);
18041 const unsigned nmy_rank_shd_bnd = my_rank_shared_boundaries_ids.size();
18043 for (
unsigned i = 0; i < nmy_rank_shd_bnd; i++)
18046 const unsigned sb = my_rank_shared_boundaries_ids[i];
18049 const unsigned nboundary_ele = this->nshared_boundary_element(sb);
18050 for (
unsigned e = 0; e < nboundary_ele; e++)
18052 if (ele_pt == this->shared_boundary_element_pt(sb,e))
18055 associated_shared_boundaries.push_back(sb);
18057 face_index_on_shared_boundary.push_back(
18058 this->face_index_at_shared_boundary(sb, e));
18065 const unsigned nassociated_shared_boundaries =
18066 associated_shared_boundaries.size();
18067 if (nassociated_shared_boundaries > 0)
18069 Flat_packed_unsigneds.push_back(3);
18070 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18071 Flat_packed_unsigneds_string.push_back(
"The element is a shared boundary element");
18073 Flat_packed_unsigneds.push_back(nassociated_shared_boundaries);
18074 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18075 std::stringstream junk;
18076 junk <<
"The elements is associated to " << nassociated_shared_boundaries <<
"shared boundaries";
18077 Flat_packed_unsigneds_string.push_back(junk.str());
18081 for (
unsigned i = 0; i < nassociated_shared_boundaries; i++)
18083 const unsigned b = associated_shared_boundaries[i];
18084 Flat_packed_unsigneds.push_back(b);
18085 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18086 std::stringstream junk;
18087 junk <<
"Element associated to shared boundary " << b <<
" of " << nassociated_shared_boundaries <<
" total associated boundaries";
18088 Flat_packed_unsigneds_string.push_back(junk.str());
18091 const unsigned f = face_index_on_shared_boundary[i];
18092 Flat_packed_unsigneds.push_back(f);
18093 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18094 std::stringstream junk2;
18095 junk2 <<
"Face index " << f <<
" for associated shared boundary " << b;
18096 Flat_packed_unsigneds_string.push_back(junk2.str());
18102 Flat_packed_unsigneds.push_back(0);
18103 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18104 Flat_packed_unsigneds_string.push_back(
"The element is not associated to any shared boundary");
18115 template<
class ELEMENT>
18120 unsigned my_rank = this->communicator_pt()->my_rank();
18121 const unsigned nproc = this->communicator_pt()->nproc();
18126 unsigned n_val=nod_pt->nvalue();
18127 Flat_packed_unsigneds.push_back(n_val);
18128 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18129 Flat_packed_unsigneds_string.push_back(
"Number of values");
18132 unsigned n_dim=nod_pt->ndim();
18136 if (this->Time_stepper_pt!=0)
18139 n_prev=this->Time_stepper_pt->ntstorage();
18145 Vector<unsigned> original_boundaries;
18148 const unsigned n_bnd = this->initial_shared_boundary_id();
18149 for (
unsigned bb=0;bb<n_bnd;bb++)
18152 if (nod_pt->is_on_boundary(bb))
18154 original_boundaries.push_back(bb);
18159 const unsigned n_original_boundaries = original_boundaries.size();
18161 if (n_original_boundaries > 0)
18164 Flat_packed_unsigneds.push_back(2);
18165 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18166 Flat_packed_unsigneds_string.push_back(
"Node is on the original boundaries");
18169 Flat_packed_unsigneds.push_back(n_original_boundaries);
18170 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18171 std::stringstream junk;
18172 junk <<
"Node is on "<< n_original_boundaries <<
" original boundaries";
18173 Flat_packed_unsigneds_string.push_back(junk.str());
18177 for (
unsigned i=0;i<n_original_boundaries;i++)
18179 Flat_packed_unsigneds.push_back(original_boundaries[i]);
18180 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18181 std::stringstream junk;
18182 junk<<
"Node is on boundary "<<original_boundaries[i]<<
" of "<< nb;
18183 Flat_packed_unsigneds_string.push_back(junk.str());
18186 Vector<double> zeta(1);
18187 nod_pt->get_coordinates_on_boundary(original_boundaries[i],zeta);
18188 Flat_packed_doubles.push_back(zeta[0]);
18194 Flat_packed_unsigneds.push_back(0);
18195 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18196 Flat_packed_unsigneds_string.push_back(
"Node is on any original boundary");
18202 bool node_on_shared_boundary =
false;
18205 const unsigned n_shd_bnd = this->nshared_boundaries(my_rank, iproc);
18206 for (
unsigned bb=0;bb<n_shd_bnd;bb++)
18209 unsigned i_bnd = this->shared_boundaries_ids(my_rank, iproc, bb);
18211 if (this->is_node_on_shared_boundary(i_bnd, nod_pt))
18213 node_on_shared_boundary =
true;
18221 if (node_on_shared_boundary)
18223 Flat_packed_unsigneds.push_back(1);
18224 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18225 Flat_packed_unsigneds_string.push_back(
"Node is on shared boundary");
18229 Vector<unsigned> shd_boundaries;
18231 for (
unsigned bb = 0; bb < n_shd_bnd; bb++)
18234 const unsigned i_bnd =
18235 this->shared_boundaries_ids(my_rank, iproc, bb);
18237 if (this->is_node_on_shared_boundary(i_bnd, nod_pt))
18239 shd_boundaries.push_back(i_bnd);
18244 const unsigned n_shd_bnd_is_on = shd_boundaries.size();
18246 Flat_packed_unsigneds.push_back(n_shd_bnd_is_on);
18247 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18248 std::stringstream junk;
18249 junk <<
"Node is on "<< n_shd_bnd_is_on <<
" shared boundaries";
18250 Flat_packed_unsigneds_string.push_back(junk.str());
18254 for (
unsigned i=0;i<n_shd_bnd_is_on;i++)
18256 Flat_packed_unsigneds.push_back(shd_boundaries[i]);
18257 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18258 std::stringstream junk;
18259 junk <<
"Node is on boundary " << shd_boundaries[i] <<
" of " << nb;
18260 Flat_packed_unsigneds_string.push_back(junk.str());
18266 unsigned shared_boundary_id = shd_boundaries[0];
18268 const unsigned n_nodes_on_shared_boundary =
18269 nsorted_shared_boundary_node(shared_boundary_id);
18271 unsigned index_node_on_shared_boundary;
18274 bool found_index_node_on_shared_boundary =
false;
18277 for (
unsigned i = 0; i < n_nodes_on_shared_boundary; i++)
18280 Node* shared_node_pt =
18281 sorted_shared_boundary_node_pt(shared_boundary_id, i);
18283 if (shared_node_pt == nod_pt)
18286 index_node_on_shared_boundary = i;
18289 found_index_node_on_shared_boundary =
true;
18297 if (!found_index_node_on_shared_boundary)
18299 std::ostringstream error_message;
18301 <<
"The index of the node on boundary ("
18302 <<shared_boundary_id<<
") was not found.\n"
18303 <<
"The node coordinates are ("<<nod_pt->x(0)<<
","
18304 <<nod_pt->x(1)<<
").\n";
18305 throw OomphLibError(
18306 error_message.str(),
18307 "RefineableTriangleMesh::get_required_nodal_information_helper()",
18308 OOMPH_EXCEPTION_LOCATION);
18312 Flat_packed_unsigneds.push_back(index_node_on_shared_boundary);
18313 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18314 std::stringstream junk2;
18315 junk2 <<
"Node index on boundary "<<
boundaries[0]<<
" is "
18316 <<index_node_on_shared_boundary;
18317 Flat_packed_unsigneds_string.push_back(junk2.str());
18324 Flat_packed_unsigneds.push_back(0);
18325 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18326 Flat_packed_unsigneds_string.push_back(
"Node is not on a shared boundary");
18341 bool node_on_shared_boundary_with_other_processors =
false;
18343 unsigned nshared_boundaries_with_other_processors_have_node = 0;
18347 for (
unsigned jproc = 0; jproc < nproc; jproc++)
18351 if (jproc != iproc)
18354 const unsigned n_jshd_bnd =
18355 this->nshared_boundaries(my_rank, jproc);
18357 for (
unsigned bb=0;bb<n_jshd_bnd;bb++)
18360 const unsigned j_shd_bnd =
18361 this->shared_boundaries_ids(my_rank, jproc, bb);
18363 if (this->is_node_on_shared_boundary(j_shd_bnd, nod_pt))
18371 node_on_shared_boundary_with_other_processors =
true;
18374 nshared_boundaries_with_other_processors_have_node++;
18385 if (node_on_shared_boundary_with_other_processors)
18387 Flat_packed_unsigneds.push_back(4);
18388 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18389 Flat_packed_unsigneds_string.push_back(
"Node is on shared boundary no related with the received processor: 4");
18395 Flat_packed_unsigneds.push_back(nshared_boundaries_with_other_processors_have_node);
18396 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18397 std::stringstream junk;
18398 junk <<
"Number of other shared boundaries that the node is on: "
18399 << nshared_boundaries_with_other_processors_have_node;
18400 Flat_packed_unsigneds_string.push_back(junk.str());
18404 unsigned counter_shd_bnd_with_other_procs_have_node = 0;
18409 Vector<unsigned> other_processor_1;
18410 Vector<unsigned> other_processor_2;
18411 Vector<unsigned> shd_bnd_ids;
18412 Vector<unsigned> indexes;
18414 for (
unsigned jproc = 0; jproc < nproc; jproc++)
18418 if (jproc != iproc)
18422 const unsigned n_jshd_bnd =
18423 this->nshared_boundaries(my_rank, jproc);
18424 for (
unsigned bb = 0; bb < n_jshd_bnd; bb++)
18427 const unsigned j_shd_bnd =
18428 this->shared_boundaries_ids(my_rank, jproc, bb);
18430 if (this->is_node_on_shared_boundary(j_shd_bnd, nod_pt))
18433 other_processor_1.push_back(my_rank);
18435 other_processor_2.push_back(jproc);
18437 shd_bnd_ids.push_back(j_shd_bnd);
18440 counter_shd_bnd_with_other_procs_have_node++;
18451 const unsigned n_other_processors = other_processor_1.size();
18453 for (
unsigned i = 0; i < n_other_processors; i++)
18456 unsigned shd_bnd_id = shd_bnd_ids[i];
18458 const unsigned n_nodes_on_shd_bnd =
18459 nsorted_shared_boundary_node(shd_bnd_id);
18462 bool found_index_node_on_shared_boundary =
false;
18464 for (
unsigned i = 0; i < n_nodes_on_shd_bnd; i++)
18467 Node* shared_node_pt =
18468 sorted_shared_boundary_node_pt(shd_bnd_id, i);
18470 if (shared_node_pt == nod_pt)
18476 indexes.push_back(i);
18479 found_index_node_on_shared_boundary =
true;
18487 if (!found_index_node_on_shared_boundary)
18489 std::ostringstream error_message;
18491 <<
"The index of the node on boundary ("
18492 <<shd_bnd_id<<
"), shared by other processors\nwas not found.\n"
18493 <<
"The node coordinates are ("<<nod_pt->x(0)<<
","
18494 <<nod_pt->x(1)<<
").\n";
18495 throw OomphLibError(
18496 error_message.str(),
18497 "RefineableTriangleMesh::get_required_nodal_information_helper()",
18498 OOMPH_EXCEPTION_LOCATION);
18507 if (counter_shd_bnd_with_other_procs_have_node !=
18508 nshared_boundaries_with_other_processors_have_node)
18510 std::ostringstream error_message;
18512 <<
"The number of shared boundaries where the node is on "
18513 <<
"is different:\n"
18514 <<
"nshared_boundaries_with_other_processors_have_node: ("
18515 << nshared_boundaries_with_other_processors_have_node
18517 <<
"counter_shd_bnd_with_other_procs_have_node: ("
18518 << counter_shd_bnd_with_other_procs_have_node
18520 throw OomphLibError(
18521 error_message.str(),
18522 "RefineableTriangleMesh::get_required_nodal_information_helper()",
18523 OOMPH_EXCEPTION_LOCATION);
18529 for (
unsigned i = 0; i < n_other_processors; i++)
18531 Flat_packed_unsigneds.push_back(other_processor_1[i]);
18532 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18533 std::stringstream junk1;
18534 junk1 <<
"Processor where the other shared boundary "
18535 <<
"has the node: " << other_processor_1[i];
18536 Flat_packed_unsigneds_string.push_back(junk1.str());
18539 Flat_packed_unsigneds.push_back(other_processor_2[i]);
18540 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18541 std::stringstream junk2;
18542 junk2 <<
"Processor where the other shared boundary "
18543 <<
"has the node: " << other_processor_2[i];
18544 Flat_packed_unsigneds_string.push_back(junk2.str());
18547 Flat_packed_unsigneds.push_back(shd_bnd_ids[i]);
18548 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18549 std::stringstream junk3;
18550 junk3 <<
"Other shared boundary id where the node is on"
18552 Flat_packed_unsigneds_string.push_back(junk3.str());
18555 Flat_packed_unsigneds.push_back(indexes[i]);
18556 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18557 std::stringstream junk4;
18558 junk4 <<
"Node index on other shared boundary "
18561 Flat_packed_unsigneds_string.push_back(junk4.str());
18569 Flat_packed_unsigneds.push_back(0);
18570 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18571 Flat_packed_unsigneds_string.push_back(
"Node is on any shared boundary with other processors");
18579 if (!node_on_shared_boundary)
18586 AlgebraicNode* alg_nod_pt=
dynamic_cast<AlgebraicNode*
>(nod_pt);
18593 unsigned update_id=alg_nod_pt->node_update_fct_id();
18594 Flat_packed_unsigneds.push_back(update_id);
18595 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18596 Flat_packed_unsigneds_string.push_back(
"Alg Node update id");
18600 unsigned n_ref_val=alg_nod_pt->nref_value();
18601 Flat_packed_unsigneds.push_back(n_ref_val);
18602 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18603 Flat_packed_unsigneds_string.push_back(
"Alg Node n ref values");
18605 for (
unsigned i_ref_val=0;i_ref_val<n_ref_val;i_ref_val++)
18607 Flat_packed_doubles.push_back(alg_nod_pt->ref_value(i_ref_val));
18611 unsigned n_geom_obj=alg_nod_pt->ngeom_object();
18612 Flat_packed_unsigneds.push_back(n_geom_obj);
18613 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18614 Flat_packed_unsigneds_string.push_back(
"Alg Node n geom objects");
18616 for (
unsigned i_geom=0;i_geom<n_geom_obj;i_geom++)
18618 GeomObject* geom_obj_pt=alg_nod_pt->geom_object_pt(i_geom);
18621 unsigned n_geom_list=alg_mesh_pt->ngeom_object_list_pt();
18624 unsigned found_geom_object=0;
18625 for (
unsigned i_list=0;i_list<n_geom_list;i_list++)
18627 if (geom_obj_pt==alg_mesh_pt->geom_object_list_pt(i_list))
18629 found_geom_object=i_list;
18632 Flat_packed_unsigneds.push_back(found_geom_object);
18633 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18634 Flat_packed_unsigneds_string.push_back(
"Found geom object");
18640 SolidNode* solid_nod_pt=
dynamic_cast<SolidNode*
>(nod_pt);
18641 if (solid_nod_pt!=0)
18643 unsigned n_solid_val=solid_nod_pt->variable_position_pt()->nvalue();
18644 for (
unsigned i_val=0;i_val<n_solid_val;i_val++)
18646 for (
unsigned t=0;
t<n_prev;
t++)
18648 Flat_packed_doubles.push_back(solid_nod_pt->variable_position_pt()->
18653 Vector<double> values_solid_node;
18654 solid_nod_pt->add_values_to_vector(values_solid_node);
18655 const unsigned nvalues_solid_node = values_solid_node.size();
18656 Flat_packed_unsigneds.push_back(nvalues_solid_node);
18657 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18658 std::stringstream junk;
18659 junk <<
"Number of values solid node: "
18660 << nvalues_solid_node;
18661 Flat_packed_unsigneds_string.push_back(junk.str());
18663 for (
unsigned i = 0; i < nvalues_solid_node; i++)
18665 Flat_packed_doubles.push_back(values_solid_node[i]);
18670 for (
unsigned i_val=0;i_val<n_val;i_val++)
18672 for (
unsigned t=0;
t<n_prev;
t++)
18674 Flat_packed_doubles.push_back(nod_pt->value(
t,i_val));
18679 for (
unsigned idim=0;idim<n_dim;idim++)
18681 for (
unsigned t=0;
t<n_prev;
t++)
18683 Flat_packed_doubles.push_back(nod_pt->x(
t,idim));
18694 template<
class ELEMENT>
18699 const unsigned n_haloed_nod = this->nhaloed_node(iproc);
18700 const unsigned haloed_node_index =
18701 this->try_to_add_haloed_node_pt(iproc,nod_pt);
18704 if (haloed_node_index==n_haloed_nod)
18706 Flat_packed_unsigneds.push_back(1);
18708 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18709 std::stringstream junk;
18710 junk <<
"Node needs to be constructed [size="
18711 << Flat_packed_unsigneds.size() <<
"]; last entry: "
18712 << Flat_packed_unsigneds[Flat_packed_unsigneds.size()-1];
18713 Flat_packed_unsigneds_string.push_back(junk.str());
18719 get_required_nodal_information_helper(iproc, nod_pt);
18723 Flat_packed_unsigneds.push_back(0);
18724 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18725 std::stringstream junk;
18726 junk <<
"Node was already added [size="
18727 << Flat_packed_unsigneds.size() <<
"]; last entry: "
18728 << Flat_packed_unsigneds[Flat_packed_unsigneds.size()-1];
18730 Flat_packed_unsigneds_string.push_back(junk.str());
18735 Flat_packed_unsigneds.push_back(haloed_node_index);
18736 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18737 Flat_packed_unsigneds_string.push_back(
"haloed node index");
18747 template<
class ELEMENT>
18752 OomphCommunicator* comm_pt = this->communicator_pt();
18756 MPI_Request request;
18759 Vector<double> received_double_values;
18760 Vector<unsigned> received_unsigned_values;
18764 unsigned send_count_double_values=Flat_packed_doubles.size();
18765 MPI_Isend(&send_count_double_values,1,MPI_UNSIGNED,
18766 send_proc,1,comm_pt->mpi_comm(),&request);
18768 int receive_count_double_values=0;
18769 MPI_Recv(&receive_count_double_values,1,MPI_INT,
18770 recv_proc,1,comm_pt->mpi_comm(),&status);
18771 MPI_Wait(&request,MPI_STATUS_IGNORE);
18773 if (send_count_double_values!=0)
18775 MPI_Isend(&Flat_packed_doubles[0],send_count_double_values,MPI_DOUBLE,
18776 send_proc,2,comm_pt->mpi_comm(),&request);
18778 if (receive_count_double_values!=0)
18780 received_double_values.resize(receive_count_double_values);
18781 MPI_Recv(&received_double_values[0],receive_count_double_values,
18782 MPI_DOUBLE,recv_proc,2,comm_pt->mpi_comm(),&status);
18784 if (send_count_double_values!=0)
18786 MPI_Wait(&request,MPI_STATUS_IGNORE);
18791 unsigned send_count_unsigned_values=Flat_packed_unsigneds.size();
18792 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18793 unsigned send_count_unsigned_string=Flat_packed_unsigneds_string.size();
18795 if (send_count_unsigned_string != send_count_unsigned_values)
18797 std::ostringstream error_message;
18799 <<
"The number of unsigned values to send to processor ("
18800 << send_proc <<
") is different from the\nnumber of annotated strings "
18801 <<
"for the communication\n\n";
18802 throw OomphLibError(error_message.str(),
18803 OOMPH_CURRENT_FUNCTION,
18804 OOMPH_EXCEPTION_LOCATION);
18806 #endif // #ifdef PARANOID
18808 MPI_Isend(&send_count_unsigned_values,1,MPI_UNSIGNED,
18809 send_proc,14,comm_pt->mpi_comm(),&request);
18811 int receive_count_unsigned_values=0;
18812 MPI_Recv(&receive_count_unsigned_values,1,MPI_INT,recv_proc,14,
18813 comm_pt->mpi_comm(),&status);
18815 MPI_Wait(&request,MPI_STATUS_IGNORE);
18817 if (send_count_unsigned_values!=0)
18819 MPI_Isend(&Flat_packed_unsigneds[0],send_count_unsigned_values,
18820 MPI_UNSIGNED,send_proc,15,comm_pt->mpi_comm(),&request);
18821 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18822 for (
unsigned i=0;i<send_count_unsigned_values;i++)
18824 oomph_info <<
"Sent:" << i <<
" to orig_proc:" << send_proc
18825 <<
" " << Flat_packed_unsigneds_string[i]
18826 <<
": " << Flat_packed_unsigneds[i] << std::endl;
18830 if (receive_count_unsigned_values!=0)
18832 received_unsigned_values.resize(receive_count_unsigned_values);
18833 MPI_Recv(&received_unsigned_values[0],receive_count_unsigned_values,
18834 MPI_UNSIGNED,recv_proc,15,comm_pt->mpi_comm(),&status);
18837 if (send_count_unsigned_values!=0)
18839 MPI_Wait(&request,MPI_STATUS_IGNORE);
18848 Flat_packed_doubles.resize(receive_count_double_values);
18849 for (
int ii=0;ii<receive_count_double_values;ii++)
18851 Flat_packed_doubles[ii]=received_double_values[ii];
18853 Flat_packed_unsigneds.resize(receive_count_unsigned_values);
18854 for (
int ii=0;ii<receive_count_unsigned_values;ii++)
18856 Flat_packed_unsigneds[ii]=received_unsigned_values[ii];
18865 template<
class ELEMENT>
18868 Vector<Node*> &new_nodes_on_domain,
18869 Vector<Vector<Vector<std::map<unsigned, Node*> > > >
18870 &other_proc_shd_bnd_node_pt,
18871 Vector<Vector<Vector<unsigned> > >
18872 &global_node_names,
18873 std::map<Vector<unsigned>,
unsigned>
18874 &node_name_to_global_index,
18875 Vector<Node*> &global_shared_node_pt)
18877 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18878 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
18879 <<
" Bool: New element needs to be constructed "
18880 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
18884 if (Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++]==1)
18888 GeneralisedElement *new_el_pt=
new ELEMENT;
18891 this->add_element_pt(new_el_pt);
18894 this->add_root_halo_element_pt(iproc, new_el_pt);
18897 FiniteElement* f_el_pt=
dynamic_cast<FiniteElement*
>(new_el_pt);
18900 this->add_halo_element_helper(iproc,f_el_pt);
18903 unsigned n_node=f_el_pt->nnode();
18905 for (
unsigned j=0;j<n_node;j++)
18907 Node* new_nod_pt=0;
18910 add_halo_node_helper(new_nod_pt,
18911 new_nodes_on_domain,
18912 other_proc_shd_bnd_node_pt,
18915 node_name_to_global_index,
18916 global_shared_node_pt);
18923 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18925 <<
"Rec:" << Counter_for_flat_packed_unsigneds
18926 <<
" Index of existing halo element "
18927 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
18931 unsigned halo_ele_index=
18932 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
18935 FiniteElement* f_el_pt=
18936 dynamic_cast<FiniteElement*
>(this->root_halo_element_pt(iproc,
18942 throw OomphLibError(
"Halo element is not a FiniteElement\n",
18943 OOMPH_CURRENT_FUNCTION,
18944 OOMPH_EXCEPTION_LOCATION);
18957 template<
class ELEMENT>
18961 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18962 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
18963 <<
" Bool: Element is associated to an original boundary "
18964 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
18968 if (Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++]==1)
18970 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18972 <<
"Rec:" << Counter_for_flat_packed_unsigneds
18973 <<
" How many boundaries are associated with the element "
18974 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
18977 const unsigned nassociated_boundaries =
18978 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
18980 for (
unsigned b = 0; b < nassociated_boundaries; b++)
18982 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18984 <<
"Rec:" << Counter_for_flat_packed_unsigneds
18985 <<
" Boundary associated to the element "
18986 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
18989 const unsigned bnd =
18990 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
18992 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18994 <<
"Rec:" << Counter_for_flat_packed_unsigneds
18995 <<
" Face index of the element "
18996 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
18999 const unsigned face_index =
19000 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19004 this->Boundary_element_pt[bnd].push_back(ele_pt);
19005 this->Face_index_at_boundary[bnd].push_back(face_index);
19010 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19011 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19012 <<
" Bool: Element is associated to a boundary-region "
19013 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19017 if (Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++]==1)
19019 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19021 <<
"Rec:" << Counter_for_flat_packed_unsigneds
19022 <<
" How many boundaries-regions are associated with the element "
19023 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19026 const unsigned nassociated_boundaries_and_regions =
19027 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19029 for (
unsigned br = 0; br < nassociated_boundaries_and_regions; br++)
19031 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19033 <<
"Rec:" << Counter_for_flat_packed_unsigneds
19034 <<
" Boundary associated to the element "
19035 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19038 const unsigned bnd =
19039 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19041 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19043 <<
"Rec:" << Counter_for_flat_packed_unsigneds
19044 <<
" Region associated to the element "
19045 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19048 const unsigned region =
19049 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19051 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19053 <<
"Rec:" << Counter_for_flat_packed_unsigneds
19054 <<
" Face index of the element in boundary-region "
19055 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19058 const unsigned face_index =
19059 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19063 this->Boundary_region_element_pt[bnd][region].push_back(ele_pt);
19064 this->Face_index_region_at_boundary[bnd][region].push_back(face_index);
19073 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19074 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19075 <<
" Bool: Element is associated to a shared boundary "
19076 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19079 if (Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++]==3)
19081 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19083 <<
"Rec:" << Counter_for_flat_packed_unsigneds
19084 <<
" How many shared boundaries are associated with the element "
19085 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19088 const unsigned nassociated_shared_boundaries =
19089 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19091 for (
unsigned b = 0; b < nassociated_shared_boundaries; b++)
19093 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19095 <<
"Rec:" << Counter_for_flat_packed_unsigneds
19096 <<
" Shared boundary associated to the element "
19097 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19100 const unsigned bnd =
19101 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19103 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19105 <<
"Rec:" << Counter_for_flat_packed_unsigneds
19106 <<
" Face index of the element associated to the shared boundary "
19107 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19111 const unsigned face_index =
19112 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19114 this->add_shared_boundary_element(bnd, ele_pt);
19115 this->add_face_index_at_shared_boundary(bnd, face_index);
19126 template<
class ELEMENT>
19128 (Node* &new_nod_pt,
19129 Vector<Node*> &new_nodes_on_domain,
19130 Vector<Vector<Vector<std::map<unsigned, Node*> > > >
19131 &other_proc_shd_bnd_node_pt,
19133 unsigned& node_index,
19134 FiniteElement*
const &new_el_pt,
19135 Vector<Vector<Vector<unsigned> > > &global_node_names,
19136 std::map<Vector<unsigned>,
unsigned> &node_name_to_global_index,
19137 Vector<Node*> &global_shared_node_pt)
19141 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19142 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19143 <<
" Bool: New node needs to be constructed "
19144 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19147 if (Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++]==1)
19151 construct_new_halo_node_helper(new_nod_pt, new_nodes_on_domain,
19152 other_proc_shd_bnd_node_pt,
19153 iproc, node_index, new_el_pt,
19155 node_name_to_global_index,
19156 global_shared_node_pt);
19160 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19161 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19162 <<
" Index of existing halo node "
19163 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19168 new_nod_pt = new_nodes_on_domain[
19169 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++]];
19171 new_el_pt->node_pt(node_index)=new_nod_pt;
19181 template<
class ELEMENT>
19183 (Node* &new_nod_pt,
19184 Vector<Node*> &new_nodes_on_domain,
19185 Vector<Vector<Vector<std::map<unsigned, Node*> > > >
19186 &other_proc_shd_bnd_node_pt,
19187 unsigned& iproc,
unsigned& node_index,
19188 FiniteElement*
const &new_el_pt,
19189 Vector<Vector<Vector<unsigned> > > &global_node_names,
19190 std::map<Vector<unsigned>,
unsigned> &node_name_to_global_index,
19191 Vector<Node*> &global_shared_node_pt)
19195 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19196 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19197 <<
" Number of values of external halo node "
19198 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19201 unsigned n_val=Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19204 TimeStepper* time_stepper_pt=this->Time_stepper_pt;
19206 unsigned n_prev=time_stepper_pt->ntstorage();
19210 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19211 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19212 <<
" Is the node on an original boundary "
19213 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19218 const unsigned node_on_original_boundaries =
19219 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19222 Vector<unsigned> original_boundaries_node_is_on;
19224 Vector<double> zeta_coordinates;
19226 unsigned n_original_boundaries_node_is_on = 0;
19228 if (node_on_original_boundaries==2)
19231 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19232 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19233 <<
" Number of boundaries the node is on: "
19234 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19237 n_original_boundaries_node_is_on =
19238 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19241 original_boundaries_node_is_on.resize(n_original_boundaries_node_is_on);
19242 zeta_coordinates.resize(n_original_boundaries_node_is_on);
19244 for (
unsigned i=0;i<n_original_boundaries_node_is_on;i++)
19247 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19248 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19249 <<
" Node is on boundary "
19250 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19253 original_boundaries_node_is_on[i] =
19254 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19255 zeta_coordinates[i] =
19256 Flat_packed_doubles[Counter_for_flat_packed_doubles++];
19263 if (node_on_original_boundaries != 0)
19265 std::ostringstream error_message;
19267 <<
"The current node is not on an original boundary, this should\n"
19268 <<
"be indicated by a zero flag. However, the read value for\n"
19269 <<
"that flag is ("<<node_on_original_boundaries<<
").\n\n";
19270 throw OomphLibError(
19271 error_message.str(),
19272 "RefineableTriangleMesh::construct_new_halo_node_helper()",
19273 OOMPH_EXCEPTION_LOCATION);
19281 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19282 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19283 <<
" Is node on shared boundary? "
19284 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19287 const unsigned is_node_on_shared_boundary =
19288 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19289 if (is_node_on_shared_boundary == 1)
19292 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19293 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19294 <<
" Number of boundaries the node is on: "
19295 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19298 const unsigned n_shd_bnd_node_is_on =
19299 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19300 Vector<unsigned> shd_bnds_node_is_on(n_shd_bnd_node_is_on);
19301 for (
unsigned i=0;i<n_shd_bnd_node_is_on;i++)
19304 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19305 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19306 <<
" Node is on boundary "
19307 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19310 shd_bnds_node_is_on[i] =
19311 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19315 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19316 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19317 <<
" Index of node on boundary "
19318 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19322 unsigned node_index_on_shared_boundary =
19323 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19327 this->sorted_shared_boundary_node_pt(shd_bnds_node_is_on[0],
19328 node_index_on_shared_boundary);
19334 if (is_node_on_shared_boundary != 0)
19336 std::ostringstream error_message;
19338 <<
"The current node is not on a shared boundary, this should\n"
19339 <<
"be indicated by a zero flag. However, the read value for\n"
19340 <<
"that flag is ("<<is_node_on_shared_boundary<<
").\n\n";
19341 throw OomphLibError(
19342 error_message.str(),
19343 "RefineableTriangleMesh::construct_new_halo_node_helper()",
19344 OOMPH_EXCEPTION_LOCATION);
19351 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19352 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19353 <<
" Is the node on shared boundaries with other processors "
19354 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19360 const unsigned is_the_node_in_shared_boundaries_with_other_processors =
19361 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19364 Vector<unsigned> other_processor_1;
19365 Vector<unsigned> other_processor_2;
19366 Vector<unsigned> other_shared_boundaries;
19367 Vector<unsigned> other_indexes;
19370 unsigned n_shd_bnd_with_other_procs_have_node = 0;
19373 if (is_the_node_in_shared_boundaries_with_other_processors == 4)
19375 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19376 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19377 <<
" In how many shared boundaries with other "
19378 <<
"processors is the node "
19379 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19384 n_shd_bnd_with_other_procs_have_node =
19385 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19388 other_processor_1.resize(n_shd_bnd_with_other_procs_have_node);
19389 other_processor_2.resize(n_shd_bnd_with_other_procs_have_node);
19390 other_shared_boundaries.resize(n_shd_bnd_with_other_procs_have_node);
19391 other_indexes.resize(n_shd_bnd_with_other_procs_have_node);
19393 for (
unsigned i = 0; i < n_shd_bnd_with_other_procs_have_node; i++)
19395 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19396 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19397 <<
" Processor where the other shared boundary"
19399 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19403 other_processor_1[i] =
19404 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19406 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19407 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19408 <<
" Processor where the other shared boundary"
19410 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19414 other_processor_2[i] =
19415 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19417 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19418 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19419 <<
" Other shared boundary id where the node is on: "
19420 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19425 other_shared_boundaries[i] =
19426 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19428 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19429 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19430 <<
" Node index on the other shared boundary "
19431 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19437 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19445 if (is_the_node_in_shared_boundaries_with_other_processors != 0)
19447 std::ostringstream error_message;
19449 <<
"The current node is not on a shared boundary with\n"
19450 <<
"other processors, this should be indicated by a zero flag.\n"
19451 <<
"However, the read value for that flag is ("
19452 <<is_the_node_in_shared_boundaries_with_other_processors<<
").\n\n";
19453 throw OomphLibError(
19454 error_message.str(),
19455 "RefineableTriangleMesh::construct_new_halo_node_helper()",
19456 OOMPH_EXCEPTION_LOCATION);
19465 if (is_node_on_shared_boundary == 1)
19470 if (node_on_original_boundaries==2)
19476 for (
unsigned i = 0; i < n_original_boundaries_node_is_on; i++)
19478 add_boundary_node(original_boundaries_node_is_on[i], new_nod_pt);
19480 Vector<double> zeta(1);
19481 zeta[0] = zeta_coordinates[i];
19482 new_nod_pt->set_coordinates_on_boundary(
19483 original_boundaries_node_is_on[i],zeta);
19489 new_nodes_on_domain.push_back(new_nod_pt);
19492 new_el_pt->node_pt(node_index) = new_nod_pt;
19502 bool found_node_in_other_shared_boundaries =
false;
19511 bool build_node_as_boundary_node =
false;
19513 if (is_the_node_in_shared_boundaries_with_other_processors == 4)
19516 build_node_as_boundary_node =
true;
19523 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
19526 Vector<Node*> found_node_pt;
19529 for (
unsigned i = 0; i < n_shd_bnd_with_other_procs_have_node; i++)
19540 unsigned oproc1 = other_processor_1[i];
19541 unsigned oproc2 = other_processor_2[i];
19542 if (other_processor_1[i] > other_processor_2[i])
19544 oproc1 = other_processor_2[i];
19545 oproc2 = other_processor_1[i];
19550 const unsigned shd_bnd_id =
19551 other_shared_boundaries[i] - initial_shd_bnd_id;
19554 const unsigned index = other_indexes[i];
19558 const unsigned n_nodes_on_other_processor =
19559 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].size();
19561 if (n_nodes_on_other_processor > 0)
19565 std::map<unsigned, Node*>::iterator it =
19566 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].
19571 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].end())
19574 found_node_in_other_shared_boundaries =
true;
19576 Node* tmp_node_pt = (*it).second;
19579 found_node_pt.push_back(tmp_node_pt);
19590 if (found_node_in_other_shared_boundaries)
19593 const unsigned n_times_node_found = found_node_pt.size();
19594 for (
unsigned j = 1; j < n_times_node_found; j++)
19596 if (found_node_pt[j-1] != found_node_pt[j])
19598 std::ostringstream error_message;
19600 <<
"The instances of the node that was found on\n"
19601 <<
"shared boundaries with other processors (but not\n"
19602 <<
"on shared boundaries with this processor) are not\n"
19604 <<
"These are the coordinates of the instances of the\n"
19606 <<
"(" << found_node_pt[j-1]->x(0) <<
", "
19607 << found_node_pt[j-1]->x(1) <<
")\n"
19608 <<
"(" << found_node_pt[j]->x(0) <<
", "
19609 << found_node_pt[j]->x(1) <<
")\n"
19610 <<
"Dont be surprised if they are the same since the "
19611 <<
"node is\nrepeated.\n";
19612 throw OomphLibError(error_message.str(),
19613 OOMPH_CURRENT_FUNCTION,
19614 OOMPH_EXCEPTION_LOCATION);
19619 #endif // #ifdef PARANOID
19625 if (is_node_on_shared_boundary == 1)
19634 if (found_node_pt[0] != new_nod_pt)
19636 std::ostringstream error_message;
19638 <<
"The pointer of the node that was found to be on a\n"
19639 <<
"shared boundary with other processor(s) and the pointer\n"
19640 <<
"of the node on shared boundary with the receiver\n"
19641 <<
"processor (iproc) are not the same. This means we have a\n"
19642 <<
"repeated node)\n"
19643 <<
"The coordinates for the nodes are:\n"
19644 <<
"(" << found_node_pt[0]->x(0) <<
", "
19645 << found_node_pt[0]->x(1) <<
")\n"
19646 <<
"(" << new_nod_pt->x(0) <<
", "
19647 << new_nod_pt->x(1) <<
")\n"
19648 <<
"Dont be surprised if they are the same since the "
19649 <<
"node is\nrepeated.\n";
19650 throw OomphLibError(error_message.str(),
19651 OOMPH_CURRENT_FUNCTION,
19652 OOMPH_EXCEPTION_LOCATION);
19663 new_nod_pt = found_node_pt[0];
19674 if (is_node_on_shared_boundary != 1)
19688 if (node_on_original_boundaries==2 || build_node_as_boundary_node)
19692 if (!found_node_in_other_shared_boundaries)
19695 if (time_stepper_pt!=0)
19697 new_nod_pt=new_el_pt->construct_boundary_node(node_index,
19702 new_nod_pt=new_el_pt->construct_boundary_node(node_index);
19709 new_el_pt->node_pt(node_index) = new_nod_pt;
19714 for (
unsigned i = 0; i < n_original_boundaries_node_is_on; i++)
19716 add_boundary_node(original_boundaries_node_is_on[i], new_nod_pt);
19718 Vector<double> zeta(1);
19719 zeta[0] = zeta_coordinates[i];
19720 new_nod_pt->set_coordinates_on_boundary(
19721 original_boundaries_node_is_on[i],zeta);
19729 if (!found_node_in_other_shared_boundaries)
19732 if (time_stepper_pt!=0)
19734 new_nod_pt=new_el_pt->construct_node(node_index, time_stepper_pt);
19738 new_nod_pt=new_el_pt->construct_node(node_index);
19744 new_el_pt->node_pt(node_index) = new_nod_pt;
19755 new_nodes_on_domain.push_back(new_nod_pt);
19759 if (!found_node_in_other_shared_boundaries)
19762 this->add_node_pt(new_nod_pt);
19766 AlgebraicNode* new_alg_nod_pt=
dynamic_cast<AlgebraicNode*
>
19771 if (new_alg_nod_pt!=0)
19780 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19781 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19782 <<
" Alg node update id "
19783 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19787 unsigned update_id=Flat_packed_unsigneds
19788 [Counter_for_flat_packed_unsigneds++];
19790 Vector<double> ref_value;
19794 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19795 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19796 <<
" Alg node # of ref values "
19797 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19800 unsigned n_ref_val=Flat_packed_unsigneds
19801 [Counter_for_flat_packed_unsigneds++];
19805 ref_value.resize(n_ref_val);
19806 for (
unsigned i_ref=0;i_ref<n_ref_val;i_ref++)
19808 ref_value[i_ref]=Flat_packed_doubles
19809 [Counter_for_flat_packed_doubles++];
19812 Vector<GeomObject*> geom_object_pt;
19819 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19820 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19821 <<
" Alg node # of geom objects "
19822 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19825 unsigned n_geom_obj=Flat_packed_unsigneds
19826 [Counter_for_flat_packed_unsigneds++];
19830 geom_object_pt.resize(n_geom_obj);
19831 for (
unsigned i_geom=0;i_geom<n_geom_obj;i_geom++)
19833 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19834 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19835 <<
" Alg node: geom object index "
19836 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19839 unsigned geom_index=Flat_packed_unsigneds
19840 [Counter_for_flat_packed_unsigneds++];
19847 geom_object_pt[i_geom]=alg_mesh_pt->
19848 geom_object_list_pt(geom_index);
19853 if (!found_node_in_other_shared_boundaries)
19857 new_alg_nod_pt->add_node_update_info
19858 (update_id,alg_mesh_pt,geom_object_pt,ref_value);
19861 alg_mesh_pt->update_node_update(new_alg_nod_pt);
19869 if (!found_node_in_other_shared_boundaries)
19872 MacroElementNodeUpdateNode* macro_nod_pt=
19873 dynamic_cast<MacroElementNodeUpdateNode*
>(new_nod_pt);
19875 if (macro_nod_pt!=0)
19879 Vector<GeomObject*> geom_object_vector_pt;
19883 MacroElementNodeUpdateMesh* macro_mesh_pt=
19884 dynamic_cast<MacroElementNodeUpdateMesh*
>(
this);
19885 geom_object_vector_pt=
19886 macro_mesh_pt->geom_object_vector_pt();
19889 Vector<double> s_in_macro_node_update_element;
19890 new_el_pt->local_coordinate_of_node
19891 (node_index,s_in_macro_node_update_element);
19894 macro_nod_pt->set_node_update_info
19895 (new_el_pt,s_in_macro_node_update_element,
19896 geom_object_vector_pt);
19902 unsigned n_new_val=new_nod_pt->nvalue();
19906 if (!found_node_in_other_shared_boundaries)
19908 if (n_val>n_new_val)
19915 BoundaryNodeBase *bnod_pt =
19916 dynamic_cast<BoundaryNodeBase*
>(new_nod_pt);
19921 if(bnod_pt->index_of_first_value_assigned_by_face_element_pt()==0)
19923 bnod_pt->index_of_first_value_assigned_by_face_element_pt()=
19924 new std::map<unsigned, unsigned>;
19928 std::map<unsigned, unsigned>* map_pt=
19929 bnod_pt->index_of_first_value_assigned_by_face_element_pt();
19933 const unsigned id_face = 0;
19935 std::map<unsigned, unsigned>::const_iterator p=map_pt->find(id_face);
19938 if(p==map_pt->end())
19942 (*map_pt)[id_face] = n_new_val;
19945 new_nod_pt->resize(n_val);
19953 SolidNode* solid_nod_pt=
dynamic_cast<SolidNode*
>(new_nod_pt);
19954 if (solid_nod_pt!=0)
19956 unsigned n_solid_val=solid_nod_pt->variable_position_pt()->nvalue();
19957 for (
unsigned i_val=0;i_val<n_solid_val;i_val++)
19959 for (
unsigned t=0;
t<n_prev;
t++)
19962 Flat_packed_doubles[Counter_for_flat_packed_doubles++];
19966 if (!found_node_in_other_shared_boundaries)
19968 solid_nod_pt->variable_position_pt()->
19969 set_value(
t, i_val, read_data);
19976 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19977 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
19978 <<
" Number of values solid node: "
19979 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
19982 const unsigned nvalues_solid_node =
19983 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
19984 Vector<double> values_solid_node(nvalues_solid_node);
19985 for (
unsigned i = 0; i < nvalues_solid_node; i++)
19987 values_solid_node[i] =
19988 Flat_packed_doubles[Counter_for_flat_packed_doubles++];
19993 if (!found_node_in_other_shared_boundaries)
19995 unsigned index = 0;
19996 solid_nod_pt->read_values_from_vector(values_solid_node, index);
20003 for (
unsigned i_val=0;i_val<n_val;i_val++)
20005 for (
unsigned t=0;
t<n_prev;
t++)
20008 Flat_packed_doubles[Counter_for_flat_packed_doubles++];
20013 if (!found_node_in_other_shared_boundaries)
20015 new_nod_pt->set_value(
t, i_val, read_data);
20023 unsigned n_dim=new_nod_pt->ndim();
20024 for (
unsigned idim=0;idim<n_dim;idim++)
20026 for (
unsigned t=0;
t<n_prev;
t++)
20029 Flat_packed_doubles[Counter_for_flat_packed_doubles++];
20034 if (!found_node_in_other_shared_boundaries)
20037 new_nod_pt->x(
t,idim) = read_data;
20049 if (n_shd_bnd_with_other_procs_have_node > 0 &&
20053 !found_node_in_other_shared_boundaries)
20061 this->update_other_proc_shd_bnd_node_helper(new_nod_pt,
20062 other_proc_shd_bnd_node_pt,
20065 other_shared_boundaries,
20068 node_name_to_global_index,
20069 global_shared_node_pt);
20079 template<
class ELEMENT>
20082 (Node* &new_node_pt,
20083 Vector<Vector<Vector<std::map<unsigned, Node*> > > >
20084 &other_proc_shd_bnd_node_pt,
20085 Vector<unsigned> &other_processor_1,
20086 Vector<unsigned> &other_processor_2,
20087 Vector<unsigned> &other_shared_boundaries,
20088 Vector<unsigned> &other_indexes,
20089 Vector<Vector<Vector<unsigned> > > &global_node_names,
20090 std::map<Vector<unsigned>,
unsigned> &node_name_to_global_index,
20091 Vector<Node*> &global_shared_node_pt)
20095 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
20100 const unsigned n_data = other_processor_1.size();
20101 #endif // #ifdef PARANOID
20104 Vector<unsigned> node_name(4);
20105 node_name[0] = other_processor_1[0];
20106 node_name[1] = other_processor_2[0];
20107 node_name[2] = other_shared_boundaries[0];
20108 node_name[3] = other_indexes[0];
20112 std::map<Vector<unsigned>,
unsigned>::iterator it =
20113 node_name_to_global_index.find(node_name);
20114 if (it==node_name_to_global_index.end())
20116 std::ostringstream error_stream;
20118 <<
"The node name does not exist in the global node names\n"
20119 <<
"This is the name of the node\n"
20120 <<
"Name: iproc, jproc, ishd_bnd, idx\n"
20121 <<
"Name: " << node_name[0] <<
", " << node_name[1] <<
", "
20122 << node_name[2] <<
", " << node_name[3] <<
"\n";
20123 throw OomphLibError(error_stream.str(),
20124 OOMPH_CURRENT_FUNCTION,
20125 OOMPH_EXCEPTION_LOCATION);
20127 #endif // #ifdef PARANOID
20130 const unsigned iglobal_node = node_name_to_global_index[node_name];
20132 global_shared_node_pt[iglobal_node] = new_node_pt;
20134 Vector<Vector<unsigned> > inode_names = global_node_names[iglobal_node];
20136 const unsigned n_names = inode_names.size();
20141 unsigned n_found_node_names_on_global_node_name = 0;
20143 for (
unsigned j = 0; j < n_data; j++)
20146 for (
unsigned k = 0; k < n_names; k++)
20149 if (inode_names[k][0] == other_processor_1[j] &&
20150 inode_names[k][1] == other_processor_2[j] &&
20151 inode_names[k][2] == other_shared_boundaries[j] &&
20152 inode_names[k][3] == other_indexes[j])
20156 n_found_node_names_on_global_node_name++;
20164 if (n_found_node_names_on_global_node_name != n_data)
20166 std::ostringstream error_stream;
20168 <<
"Not all the node names of the current node were found on the\n"
20169 <<
"global node names. This happened when adding the node pointer\n"
20170 <<
"to the data structure that keeps tracks of nodes on shared\n"
20171 <<
"boundaries with other processors\n\n"
20172 <<
"These are the names of the current node\n"
20173 <<
"Name k: iproc, jproc, ishd_bnd, idx\n";
20174 for (
unsigned j = 0; j < n_data; j++)
20176 error_stream<<
"Name("<<j<<
"): "
20177 <<other_processor_1[j] <<
", "
20178 <<other_processor_2[j] <<
", "
20179 <<other_shared_boundaries[j] <<
", "
20180 <<other_indexes[j] <<
"\n";
20184 <<
"\n\nThese are the names of the global node\n"
20185 <<
"Name k: iproc, jproc, ishd_bnd, idx\n";
20186 for (
unsigned k = 0; k < n_names; k++)
20188 error_stream<<
"Name("<<k<<
"): "
20189 <<inode_names[k][0] <<
", "
20190 <<inode_names[k][1] <<
", "
20191 <<inode_names[k][2] <<
", "
20192 <<inode_names[k][3] <<
"\n";
20195 throw OomphLibError(error_stream.str(),
20196 OOMPH_CURRENT_FUNCTION,
20197 OOMPH_EXCEPTION_LOCATION);
20199 #endif // #ifdef PARANOID
20202 for (
unsigned j = 0; j < n_names; j++)
20205 const unsigned iproc = inode_names[j][0];
20206 const unsigned jproc = inode_names[j][1];
20207 const unsigned ishd_bnd = inode_names[j][2] - initial_shd_bnd_id;
20208 const unsigned index = inode_names[j][3];
20214 other_proc_shd_bnd_node_pt[iproc][jproc][ishd_bnd][index]
20219 other_proc_shd_bnd_node_pt[jproc][iproc][ishd_bnd][index]
20239 template <
class ELEMENT>
20242 target_domain_for_local_non_halo_element)
20244 oomph_info <<
"Load balance (unstructured mesh) [BEGIN]" << std::endl;
20248 if (!this->is_mesh_distributed())
20250 std::ostringstream warning_message;
20252 <<
"\n===============================================================\n"
20253 <<
"The load balancing can only be performed in distributed meshes,\n"
20254 <<
"your mesh has not been distributed.\n"
20255 <<
"===============================================================\n\n";
20256 OomphLibWarning(warning_message.str(),
20257 OOMPH_CURRENT_FUNCTION,
20258 OOMPH_EXCEPTION_LOCATION);
20264 const unsigned nproc = this->communicator_pt()->nproc();
20266 const unsigned my_rank = this->communicator_pt()->my_rank();
20271 std::ostringstream warning_message;
20273 <<
"\n===============================================================\n"
20274 <<
"The load balancing can only be performed when there are at least\n"
20275 <<
"two procesors, the current number of processors is one.\n"
20276 <<
"===============================================================\n\n";
20277 OomphLibWarning(warning_message.str(),
20278 OOMPH_CURRENT_FUNCTION,
20279 OOMPH_EXCEPTION_LOCATION);
20285 double t_start_overall_load_balance=0.0;
20286 if (Print_timings_level_load_balance>1)
20288 t_start_overall_load_balance=TimingHelpers::timer();
20292 const unsigned nelement_before_load_balance = this->nelement();
20297 if (nnon_halo_element() !=
20298 target_domain_for_local_non_halo_element.size())
20300 std::ostringstream error_message;
20302 <<
"The number of non halo elements in the current mesh ("
20303 << nnon_halo_element() <<
") and the number\n"
20304 <<
"of target areas for the local non halo elements ("
20305 << target_domain_for_local_non_halo_element.size()
20306 <<
") is different\n\n";
20307 throw OomphLibError(error_message.str(),
20308 OOMPH_CURRENT_FUNCTION,
20309 OOMPH_EXCEPTION_LOCATION);
20314 Vector<FiniteElement*> backed_up_ele_pt(nelement_before_load_balance);
20315 for (
unsigned e = 0; e < nelement_before_load_balance; e++)
20317 backed_up_ele_pt[e] = this->finite_element_pt(e);
20325 double tt_start_get_domains_halo_elements=0.0;
20326 if (Print_timings_level_load_balance>1)
20328 tt_start_get_domains_halo_elements=TimingHelpers::timer();
20342 Vector<Vector<unsigned> > new_domains_haloed_elements(nproc);
20345 Vector<Vector<unsigned> > new_domains_halo_elements(nproc);
20349 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20353 if (iproc != my_rank)
20356 const unsigned n_halo_iproc = this->nroot_halo_element(iproc);
20358 new_domains_halo_elements[iproc].resize(n_halo_iproc);
20361 const unsigned n_haloed_iproc = this->nroot_haloed_element(iproc);
20363 new_domains_haloed_elements[iproc].resize(n_haloed_iproc);
20369 Vector<unsigned> counter_for_found_haloed_elements(nproc, 0);
20376 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20380 if (iproc != my_rank)
20383 const unsigned n_haloed_iproc = this->nroot_haloed_element(iproc);
20386 for (
unsigned ihd = 0; ihd < n_haloed_iproc; ihd++)
20389 GeneralisedElement* haloed_ele_pt =
20390 this->root_haloed_element_pt(iproc, ihd);
20393 unsigned nh_count4 = 0;
20395 for (
unsigned e = 0; e < nelement_before_load_balance; e++)
20398 GeneralisedElement* ele_pt = this->element_pt(e);
20400 if (!ele_pt->is_halo())
20407 if (ele_pt == haloed_ele_pt)
20410 const unsigned element_domain =
20411 target_domain_for_local_non_halo_element[nh_count4-1];
20416 new_domains_haloed_elements[iproc][ihd] = element_domain;
20419 counter_for_found_haloed_elements[iproc]++;
20440 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20444 if (iproc != my_rank)
20447 const unsigned n_haloed_iproc = this->nroot_haloed_element(iproc);
20451 if (n_haloed_iproc != counter_for_found_haloed_elements[iproc])
20453 std::ostringstream error_message;
20455 <<
"The independent counting of found haloed elements ("
20456 << counter_for_found_haloed_elements[iproc] <<
") with processor ("
20457 << iproc <<
") is not equal to the number of haloed elements ("
20458 << n_haloed_iproc <<
") with processor (" << iproc <<
")\n";
20459 throw OomphLibError(error_message.str(),
20460 OOMPH_CURRENT_FUNCTION,
20461 OOMPH_EXCEPTION_LOCATION);
20475 Vector<unsigned> new_domains_haloed_flat_unsigned;
20478 Vector<int> nhaloed_elements_with_iproc(nproc);
20479 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20483 if (iproc != my_rank)
20486 const unsigned n_haloed_ele_iproc = this->nroot_haloed_element(iproc);
20488 nhaloed_elements_with_iproc[iproc] = n_haloed_ele_iproc;
20491 for (
unsigned i = 0; i < n_haloed_ele_iproc; i++)
20493 new_domains_haloed_flat_unsigned.push_back(
20494 new_domains_haloed_elements[iproc][i]);
20502 Vector<int> offset_haloed_elements_with_iproc(nproc);
20503 offset_haloed_elements_with_iproc[0] = 0;
20504 for (
unsigned ip = 1; ip < nproc; ip++)
20507 offset_haloed_elements_with_iproc[ip] =
20508 offset_haloed_elements_with_iproc[ip-1] +
20509 nhaloed_elements_with_iproc[ip-1];
20518 unsigned counter_halo_ele_with_all_procs = 0;
20522 Vector<int> nhalo_elements_with_iproc(nproc);
20525 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20529 if (iproc != my_rank)
20532 const unsigned n_halo_ele_iproc = this->nroot_halo_element(iproc);
20534 nhalo_elements_with_iproc[iproc] = n_halo_ele_iproc;
20536 counter_halo_ele_with_all_procs+= n_halo_ele_iproc;
20542 Vector<int> offset_halo_elements_with_iproc(nproc);
20543 offset_halo_elements_with_iproc[0] = 0;
20544 for (
unsigned ip = 1; ip < nproc; ip++)
20547 offset_halo_elements_with_iproc[ip] =
20548 offset_halo_elements_with_iproc[ip-1] +
20549 nhalo_elements_with_iproc[ip-1];
20558 new_domains_halo_flat_unsigned(counter_halo_ele_with_all_procs);
20562 MPI_Alltoallv(&new_domains_haloed_flat_unsigned[0],
20563 &nhaloed_elements_with_iproc[0],
20564 &offset_haloed_elements_with_iproc[0],
20566 &new_domains_halo_flat_unsigned[0],
20567 &nhalo_elements_with_iproc[0],
20568 &offset_halo_elements_with_iproc[0],
20570 this->communicator_pt()->mpi_comm());
20576 unsigned counter_new_domains_halo_ele = 0;
20577 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20581 if (iproc != my_rank)
20584 const unsigned ntmp_halo_elements_with_iproc =
20585 nhalo_elements_with_iproc[iproc];
20588 for (
unsigned i = 0; i < ntmp_halo_elements_with_iproc; i++)
20592 new_domains_halo_elements[iproc][i] =
20593 new_domains_halo_flat_unsigned[counter_new_domains_halo_ele++];
20599 if (Print_timings_level_load_balance>1)
20601 oomph_info <<
"CPU for getting domains halo elements (load balance) [1]: "
20602 <<TimingHelpers::timer()-tt_start_get_domains_halo_elements
20617 double tt_start_get_fe_version_from_ge_halo_ed=0.0;
20618 if (Print_timings_level_load_balance>1)
20620 tt_start_get_fe_version_from_ge_halo_ed=TimingHelpers::timer();
20624 Vector<Vector<FiniteElement*> > f_halo_element_pt(nproc);
20626 Vector<Vector<FiniteElement*> > f_haloed_element_pt(nproc);
20628 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20631 if (iproc != my_rank)
20634 const unsigned nhalo_ele_iproc = this->nroot_halo_element(iproc);
20636 Vector<GeneralisedElement*> halo_element_pt_iproc =
20637 this->root_halo_element_pt(iproc);
20639 f_halo_element_pt[iproc].resize(nhalo_ele_iproc);
20641 for (
unsigned ih = 0; ih < nhalo_ele_iproc; ih++)
20644 FiniteElement* ele_pt =
20645 dynamic_cast<FiniteElement*
>(halo_element_pt_iproc[ih]);
20647 f_halo_element_pt[iproc][ih] = ele_pt;
20651 const unsigned nhaloed_ele_iproc = this->nroot_haloed_element(iproc);
20653 Vector<GeneralisedElement*> haloed_element_pt_iproc =
20654 this->root_haloed_element_pt(iproc);
20656 f_haloed_element_pt[iproc].resize(nhaloed_ele_iproc);
20658 for (
unsigned ihd = 0; ihd < nhaloed_ele_iproc; ihd++)
20661 FiniteElement* ele_pt =
20662 dynamic_cast<FiniteElement*
>(haloed_element_pt_iproc[ihd]);
20664 f_haloed_element_pt[iproc][ihd] = ele_pt;
20673 if (Print_timings_level_load_balance>1)
20675 oomph_info <<
"CPU for getting finite element versions from generalised halo(ed) elements (load balance) [2]: "
20676 <<TimingHelpers::timer()-tt_start_get_fe_version_from_ge_halo_ed
20693 double tt_start_prepare_element_to_send=0.0;
20694 if (Print_timings_level_load_balance>1)
20696 tt_start_prepare_element_to_send=TimingHelpers::timer();
20700 Vector<Vector<FiniteElement*> > elements_to_send_pt(nproc);
20704 std::map<Data*,std::set<unsigned> >
20705 processors_associated_with_data_before_load_balance;
20709 unsigned nh_count3 = 0;
20710 for (
unsigned e = 0; e < nelement_before_load_balance; e++)
20713 FiniteElement *ele_pt = this->finite_element_pt(e);
20715 if (!(ele_pt->is_halo()))
20718 const unsigned element_domain =
20719 target_domain_for_local_non_halo_element[nh_count3++];
20722 elements_to_send_pt[element_domain].push_back(ele_pt);
20725 const unsigned n_nodes = ele_pt->nnode();
20727 for (
unsigned j = 0; j < n_nodes; j++)
20730 Node* node_pt = ele_pt->node_pt(j);
20732 processors_associated_with_data_before_load_balance[node_pt].
20733 insert(element_domain);
20745 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20748 if (iproc != my_rank)
20751 const unsigned n_halo_ele_iproc = this->nroot_halo_element(iproc);
20753 Vector<GeneralisedElement*> halo_element_pt_iproc =
20754 this->root_halo_element_pt(iproc);
20756 for (
unsigned ih = 0; ih < n_halo_ele_iproc; ih++)
20759 const unsigned element_domain =
20760 new_domains_halo_elements[iproc][ih];
20763 FiniteElement* ele_pt =
20764 dynamic_cast<FiniteElement*
>(halo_element_pt_iproc[ih]);
20767 const unsigned n_nodes = ele_pt->nnode();
20769 for (
unsigned j = 0; j < n_nodes; j++)
20772 Node* node_pt = ele_pt->node_pt(j);
20775 processors_associated_with_data_before_load_balance[node_pt].
20776 insert(element_domain);
20787 if (Print_timings_level_load_balance>1)
20789 oomph_info <<
"CPU for preparing elements to send to other processors (load balance) [3]: "
20790 <<TimingHelpers::timer()-tt_start_prepare_element_to_send
20813 double tt_start_compute_new_local_halo_elements=0.0;
20814 if (Print_timings_level_load_balance>1)
20816 tt_start_compute_new_local_halo_elements=TimingHelpers::timer();
20846 Vector<Vector<Vector<FiniteElement*> > > new_local_halo_element_pt(nproc);
20849 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20852 new_local_halo_element_pt[iproc].resize(nproc);
20856 Vector<std::map<FiniteElement*,bool> > new_local_halo_already_added(nproc);
20860 unsigned nh_count5 = 0;
20861 for (
unsigned e = 0; e < nelement_before_load_balance; e++)
20864 FiniteElement *ele_pt = this->finite_element_pt(e);
20866 if (!(ele_pt->is_halo()))
20869 const unsigned ele_domain =
20870 target_domain_for_local_non_halo_element[nh_count5++];
20873 if (ele_domain != iproc)
20876 const unsigned nnodes = ele_pt->nnode();
20878 for (
unsigned j = 0; j < nnodes; j++)
20880 Node* node_pt = ele_pt->node_pt(j);
20883 std::set<unsigned>::iterator it =
20884 processors_associated_with_data_before_load_balance[node_pt].
20888 processors_associated_with_data_before_load_balance[node_pt].
20895 if (!new_local_halo_already_added[ele_domain][ele_pt])
20899 new_local_halo_element_pt[iproc][ele_domain].
20902 new_local_halo_already_added[ele_domain][ele_pt] =
true;
20940 for (
unsigned jproc = 0; jproc < nproc; jproc++)
20944 if (jproc != my_rank)
20947 const unsigned n_halo_ele_jproc = this->nroot_halo_element(jproc);
20949 Vector<GeneralisedElement*> halo_element_pt_jproc =
20950 this->root_halo_element_pt(jproc);
20953 for (
unsigned jh = 0; jh < n_halo_ele_jproc; jh++)
20956 const unsigned ele_domain = new_domains_halo_elements[jproc][jh];
20987 if (ele_domain != iproc)
20990 FiniteElement* ele_pt =
20991 dynamic_cast<FiniteElement*
>(halo_element_pt_jproc[jh]);
20993 const unsigned nnodes = ele_pt->nnode();
20995 for (
unsigned j = 0; j < nnodes; j++)
20998 Node* node_pt = ele_pt->node_pt(j);
21002 std::set<unsigned>::iterator it =
21003 processors_associated_with_data_before_load_balance[node_pt].
21007 processors_associated_with_data_before_load_balance[node_pt].end())
21014 if (!new_local_halo_already_added[ele_domain][ele_pt])
21018 new_local_halo_element_pt[iproc][ele_domain].
21020 new_local_halo_already_added[ele_domain][ele_pt] =
true;
21049 if (Print_timings_level_load_balance>1)
21051 oomph_info <<
"CPU for computing new local halo elements (load balance) [4]: "
21052 <<TimingHelpers::timer()-tt_start_compute_new_local_halo_elements
21071 double tt_start_compute_new_local_shd_bnd_ele=0.0;
21072 if (Print_timings_level_load_balance>1)
21074 tt_start_compute_new_local_shd_bnd_ele=TimingHelpers::timer();
21079 Vector<Vector<Vector<FiniteElement*> > >
21080 new_local_halo_shared_boundary_element_pt(nproc);
21081 Vector<Vector<Vector<unsigned> > >
21082 new_local_halo_shared_boundary_element_face_index(nproc);
21085 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21087 new_local_halo_shared_boundary_element_pt[iproc].resize(nproc);
21088 new_local_halo_shared_boundary_element_face_index[iproc].resize(nproc);
21096 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21102 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
21104 this->get_shared_boundary_elements_and_face_indexes(
21105 new_local_halo_element_pt[iproc][jproc],
21106 new_local_halo_element_pt[jproc][iproc],
21107 new_local_halo_shared_boundary_element_pt[iproc][jproc],
21108 new_local_halo_shared_boundary_element_face_index[iproc][jproc],
21109 new_local_halo_shared_boundary_element_pt[jproc][iproc],
21110 new_local_halo_shared_boundary_element_face_index[jproc][iproc]);
21115 if (Print_timings_level_load_balance>1)
21117 oomph_info <<
"CPU for computing new local shared boundary elements (load balance) [5]: "
21118 <<TimingHelpers::timer()-tt_start_compute_new_local_shd_bnd_ele
21137 double tt_start_send_elements_to_other_processors=0.0;
21138 if (Print_timings_level_load_balance>1)
21140 tt_start_send_elements_to_other_processors=TimingHelpers::timer();
21146 this->sort_nodes_on_shared_boundaries();
21149 Vector<Vector<FiniteElement*> > received_elements_pt(nproc);
21156 Vector<Vector<Vector<FiniteElement*> > >
21157 new_received_haloed_shared_boundary_element_pt(nproc);
21158 Vector<Vector<Vector<unsigned> > >
21159 new_received_haloed_shared_boundary_element_face_index(nproc);
21164 Vector<Vector<Vector<std::map<unsigned, Node*> > > >
21165 other_proc_shd_bnd_node_pt(nproc);
21167 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21170 other_proc_shd_bnd_node_pt[iproc].resize(nproc);
21171 for (
unsigned jproc = 0; jproc < nproc; jproc++)
21174 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
21175 const unsigned final_shd_bnd_id = this->final_shared_boundary_id();
21176 const unsigned n_shared_bound = final_shd_bnd_id - initial_shd_bnd_id;
21177 other_proc_shd_bnd_node_pt[iproc][jproc].resize(n_shared_bound);
21186 Vector<Vector<Vector<unsigned> > > global_node_names;
21190 std::map<Vector<unsigned>,
unsigned> node_name_to_global_index;
21193 Vector<Node*> global_shared_node_pt;
21198 compute_global_node_names_and_shared_nodes(other_proc_shd_bnd_node_pt,
21200 node_name_to_global_index,
21201 global_shared_node_pt);
21206 Vector<Vector<std::map<unsigned,FiniteElement*> > >
21207 received_old_haloed_element_pt(nproc);
21214 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21216 received_old_haloed_element_pt[iproc].resize(nproc);
21221 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21223 if (iproc != my_rank)
21230 Vector<FiniteElement*> currently_sent_elements;
21232 Vector<Node*> currently_sent_nodes;
21235 Flat_packed_unsigneds.clear();
21236 Flat_packed_doubles.clear();
21237 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21238 Flat_packed_unsigneds_string.clear();
21242 const unsigned nelements_to_send = elements_to_send_pt[iproc].size();
21248 Flat_packed_unsigneds.push_back(nelements_to_send);
21249 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21250 std::stringstream junk;
21251 junk <<
"Number of elements to send from processor " << my_rank
21252 <<
" to processor " << iproc <<
": ("
21253 << nelements_to_send <<
")";
21254 Flat_packed_unsigneds_string.push_back(junk.str());
21258 for (
unsigned e = 0; e < nelements_to_send; e++)
21261 FiniteElement* send_ele_pt = elements_to_send_pt[iproc][e];
21264 const unsigned ncurrently_sent_elements =
21265 currently_sent_elements.size();
21268 const unsigned index_ele = try_to_add_element_pt_load_balance(
21269 currently_sent_elements, send_ele_pt);
21272 if (index_ele == ncurrently_sent_elements)
21274 Flat_packed_unsigneds.push_back(1);
21275 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21276 Flat_packed_unsigneds_string.push_back(
"Element needs to be constructed");
21280 get_required_elemental_information_load_balance_helper(
21282 f_haloed_element_pt,
21286 const unsigned nnodes = send_ele_pt->nnode();
21289 for (
unsigned j = 0; j < nnodes; j++)
21291 Node* node_pt = send_ele_pt->node_pt(j);
21294 add_node_load_balance_helper(iproc,
21296 currently_sent_nodes,
21304 Flat_packed_unsigneds.push_back(0);
21305 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21306 Flat_packed_unsigneds_string.push_back(
"Element already exists");
21308 Flat_packed_unsigneds.push_back(index_ele);
21309 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21310 Flat_packed_unsigneds_string.push_back(
"Index of existing element");
21329 for (
unsigned jproc = 0; jproc < nproc; jproc++)
21335 const unsigned njproc_iproc_new_local_halo_shared_boundary_ele =
21336 new_local_halo_shared_boundary_element_pt[jproc][iproc].size();
21339 Vector<unsigned> new_local_halo_shared_boundary_ele_index;
21343 unsigned nfound_new_local_halo_shared_bound_ele_index = 0;
21346 unsigned nnon_halo_new_local_halo_shared_bound_ele = 0;
21350 for (
unsigned e = 0;
21351 e < njproc_iproc_new_local_halo_shared_boundary_ele; e++)
21354 FiniteElement* shared_ele_pt =
21355 new_local_halo_shared_boundary_element_pt[jproc][iproc][e];
21359 if (!shared_ele_pt->is_halo())
21361 nnon_halo_new_local_halo_shared_bound_ele++;
21366 const unsigned ncurrently_sent_elements =
21367 currently_sent_elements.size();
21369 for (
unsigned ics = 0; ics < ncurrently_sent_elements; ics++)
21371 FiniteElement* currently_sent_ele_pt =
21372 currently_sent_elements[ics];
21375 if (currently_sent_ele_pt == shared_ele_pt)
21379 new_local_halo_shared_boundary_ele_index.push_back(ics);
21382 nfound_new_local_halo_shared_bound_ele_index++;
21394 if (nfound_new_local_halo_shared_bound_ele_index !=
21395 nnon_halo_new_local_halo_shared_bound_ele)
21397 std::ostringstream error_message;
21399 <<
"Was only possible to identify ("
21400 << nfound_new_local_halo_shared_bound_ele_index <<
") of ("
21401 << nnon_halo_new_local_halo_shared_bound_ele <<
") shared "
21402 <<
"elements between\nprocessor ("<<iproc<<
") and ("<<jproc<<
") "
21403 <<
"when sending elements to processor ("<<iproc<<
")\n\n";
21404 throw OomphLibError(error_message.str(),
21405 OOMPH_CURRENT_FUNCTION,
21406 OOMPH_EXCEPTION_LOCATION);
21411 Flat_packed_unsigneds.push_back(9999);
21412 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21413 std::stringstream junk;
21414 junk <<
"Flag for synchronisation 9999";
21415 Flat_packed_unsigneds_string.push_back(junk.str());
21420 Flat_packed_unsigneds.push_back(nnon_halo_new_local_halo_shared_bound_ele);
21421 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21422 std::stringstream junk2;
21423 junk2 <<
"Number of new local halo shared boundary elements "
21424 << nnon_halo_new_local_halo_shared_bound_ele;
21425 Flat_packed_unsigneds_string.push_back(junk2.str());
21430 unsigned counter_nonhalo_sent = 0;
21433 for (
unsigned e = 0;
21434 e < njproc_iproc_new_local_halo_shared_boundary_ele; e++)
21437 FiniteElement* shared_ele_pt =
21438 new_local_halo_shared_boundary_element_pt[jproc][iproc][e];
21442 if (!shared_ele_pt->is_halo())
21446 const unsigned ele_index =
21447 new_local_halo_shared_boundary_ele_index[counter_nonhalo_sent++];
21449 const unsigned face_index =
21450 new_local_halo_shared_boundary_element_face_index[jproc][iproc][e];
21454 Flat_packed_unsigneds.push_back(ele_index);
21455 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21456 std::stringstream junk;
21457 junk <<
"The index of the halo shared boundary element "
21459 Flat_packed_unsigneds_string.push_back(junk.str());
21464 Flat_packed_unsigneds.push_back(face_index);
21465 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21466 std::stringstream junk2;
21467 junk2 <<
"The face index of the halo shared boundary element "
21469 Flat_packed_unsigneds_string.push_back(junk2.str());
21482 int send_proc =
static_cast<int>(iproc);
21484 int recv_proc =
static_cast<int>(iproc);
21485 send_and_receive_elements_nodes_info(send_proc, recv_proc);
21492 Vector<FiniteElement*> currently_created_elements;
21494 Vector<Node*> currently_created_nodes;
21497 Counter_for_flat_packed_doubles=0;
21498 Counter_for_flat_packed_unsigneds=0;
21500 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21501 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
21502 <<
" Number of elements need to be constructed "
21503 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
21508 const unsigned nelements_to_create =
21509 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
21511 for (
unsigned e = 0; e < nelements_to_create; e++)
21515 create_element_load_balance_helper(iproc,
21516 f_haloed_element_pt,
21517 received_old_haloed_element_pt,
21518 currently_created_elements,
21519 currently_created_nodes,
21520 other_proc_shd_bnd_node_pt,
21522 node_name_to_global_index,
21523 global_shared_node_pt);
21529 const unsigned nreceived_elements = currently_created_elements.size();
21530 received_elements_pt[iproc].resize(nreceived_elements);
21531 for (
unsigned e = 0; e < nreceived_elements; e++)
21532 {received_elements_pt[iproc][e] = currently_created_elements[e];}
21538 new_received_haloed_shared_boundary_element_pt[iproc].resize(nproc);
21539 new_received_haloed_shared_boundary_element_face_index[iproc].resize(nproc);
21542 for (
unsigned jproc = 0; jproc < nproc; jproc++)
21545 const unsigned synchronisation_flag =
21546 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
21548 if (synchronisation_flag != 9999)
21550 std::ostringstream error_message;
21552 <<
"The synchronisation flag was not read, the\n"
21553 <<
"information sent between processor (" << my_rank <<
") "
21554 <<
"and ("<< iproc <<
")\nis no longer synchronised\n\n";
21555 throw OomphLibError(error_message.str(),
21556 OOMPH_CURRENT_FUNCTION,
21557 OOMPH_EXCEPTION_LOCATION);
21563 const unsigned niproc_jproc_new_received_haloed_shared_boundary_ele =
21564 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
21567 for (
unsigned e = 0;
21568 e < niproc_jproc_new_received_haloed_shared_boundary_ele; e++)
21572 const unsigned ele_index =
21573 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
21576 const unsigned face_index =
21577 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
21580 FiniteElement* shared_ele_pt =
21581 currently_created_elements[ele_index];
21586 new_received_haloed_shared_boundary_element_pt[iproc][jproc].
21587 push_back(shared_ele_pt);
21589 new_received_haloed_shared_boundary_element_face_index[iproc][jproc].
21590 push_back(face_index);
21601 if (Print_timings_level_load_balance>1)
21603 oomph_info <<
"CPU for sending elements to their new processors (load balance) [6]: "
21604 <<TimingHelpers::timer()-tt_start_send_elements_to_other_processors
21623 double tt_start_compute_additional_shared_boundaries=0.0;
21624 if (Print_timings_level_load_balance>1)
21626 tt_start_compute_additional_shared_boundaries=TimingHelpers::timer();
21632 Vector<Vector<FiniteElement*> >
21633 tmp_group1_shared_boundary_element_pt(nproc);
21634 Vector<Vector<unsigned> >
21635 tmp_group1_shared_boundary_element_face_index(nproc);
21636 Vector<Vector<FiniteElement*> >
21637 tmp_group2_shared_boundary_element_pt(nproc);
21638 Vector<Vector<unsigned> >
21639 tmp_group2_shared_boundary_element_face_index(nproc);
21663 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21665 if (my_rank < iproc)
21668 this->get_shared_boundary_elements_and_face_indexes(
21669 received_elements_pt[iproc], elements_to_send_pt[iproc],
21670 tmp_group1_shared_boundary_element_pt[iproc],
21671 tmp_group1_shared_boundary_element_face_index[iproc],
21672 tmp_group2_shared_boundary_element_pt[iproc],
21673 tmp_group2_shared_boundary_element_face_index[iproc]);
21676 else if (my_rank > iproc)
21679 this->get_shared_boundary_elements_and_face_indexes(
21680 elements_to_send_pt[iproc], received_elements_pt[iproc],
21681 tmp_group1_shared_boundary_element_pt[iproc],
21682 tmp_group1_shared_boundary_element_face_index[iproc],
21683 tmp_group2_shared_boundary_element_pt[iproc],
21684 tmp_group2_shared_boundary_element_face_index[iproc]);
21691 if (Print_timings_level_load_balance>1)
21693 oomph_info <<
"CPU for computing additional shared boundaries (load balance) [7]: "
21694 <<TimingHelpers::timer()-tt_start_compute_additional_shared_boundaries
21713 double tt_start_sort_shared_boundaries=0.0;
21714 if (Print_timings_level_load_balance>1)
21716 tt_start_sort_shared_boundaries=TimingHelpers::timer();
21737 Vector<Vector<FiniteElement*> > new_shared_boundary_element_pt(nproc);
21738 Vector<Vector<unsigned> > new_shared_boundary_element_face_index(nproc);
21739 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21742 if (my_rank < iproc)
21746 for (
unsigned jproc = 0; jproc < nproc; jproc++)
21749 if (jproc != my_rank)
21752 const unsigned nrecvd_haloed_shared_bound_ele_jproc_iproc =
21753 new_received_haloed_shared_boundary_element_pt[jproc][iproc].size();
21754 for (
unsigned e = 0;
21755 e < nrecvd_haloed_shared_bound_ele_jproc_iproc; e++)
21758 FiniteElement* ele_pt =
21759 new_received_haloed_shared_boundary_element_pt[jproc][iproc][e];
21761 const unsigned face_index =
21762 new_received_haloed_shared_boundary_element_face_index[jproc][iproc][e];
21765 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
21766 new_shared_boundary_element_face_index[iproc].push_back(face_index);
21776 const unsigned nlocal_haloed_shared_bound_ele_iproc_my_rank =
21777 new_local_halo_shared_boundary_element_pt[iproc][my_rank].size();
21778 for (
unsigned e = 0;
21779 e < nlocal_haloed_shared_bound_ele_iproc_my_rank; e++)
21782 FiniteElement* ele_pt =
21783 new_local_halo_shared_boundary_element_pt[iproc][my_rank][e];
21785 const unsigned face_index =
21786 new_local_halo_shared_boundary_element_face_index[iproc][my_rank][e];
21791 if (!ele_pt->is_halo())
21794 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
21795 new_shared_boundary_element_face_index[iproc].push_back(face_index);
21802 const unsigned ntmp_group1_shared_bound_ele_iproc =
21803 tmp_group1_shared_boundary_element_pt[iproc].size();
21804 for (
unsigned e = 0; e < ntmp_group1_shared_bound_ele_iproc; e++)
21807 FiniteElement* ele_pt =
21808 tmp_group1_shared_boundary_element_pt[iproc][e];
21810 const unsigned face_index =
21811 tmp_group1_shared_boundary_element_face_index[iproc][e];
21814 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
21815 new_shared_boundary_element_face_index[iproc].push_back(face_index);
21821 else if (my_rank > iproc)
21829 const unsigned nlocal_haloed_shared_bound_ele_iproc_my_rank =
21830 new_local_halo_shared_boundary_element_pt[iproc][my_rank].size();
21831 for (
unsigned e = 0;
21832 e < nlocal_haloed_shared_bound_ele_iproc_my_rank; e++)
21835 FiniteElement* ele_pt =
21836 new_local_halo_shared_boundary_element_pt[iproc][my_rank][e];
21838 const unsigned face_index =
21839 new_local_halo_shared_boundary_element_face_index[iproc][my_rank][e];
21844 if (!ele_pt->is_halo())
21847 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
21848 new_shared_boundary_element_face_index[iproc].push_back(face_index);
21853 for (
unsigned jproc = 0; jproc < nproc; jproc++)
21856 if (jproc != my_rank)
21860 const unsigned nrecvd_haloed_shared_bound_ele_jproc_iproc =
21861 new_received_haloed_shared_boundary_element_pt[jproc][iproc].size();
21862 for (
unsigned e = 0;
21863 e < nrecvd_haloed_shared_bound_ele_jproc_iproc; e++)
21866 FiniteElement* ele_pt =
21867 new_received_haloed_shared_boundary_element_pt[jproc][iproc][e];
21869 const unsigned face_index =
21870 new_received_haloed_shared_boundary_element_face_index[jproc][iproc][e];
21873 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
21874 new_shared_boundary_element_face_index[iproc].push_back(face_index);
21884 const unsigned ntmp_group2_shared_bound_ele_iproc =
21885 tmp_group2_shared_boundary_element_pt[iproc].size();
21886 for (
unsigned e = 0; e < ntmp_group2_shared_bound_ele_iproc; e++)
21889 FiniteElement* ele_pt =
21890 tmp_group2_shared_boundary_element_pt[iproc][e];
21892 const unsigned face_index =
21893 tmp_group2_shared_boundary_element_face_index[iproc][e];
21896 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
21897 new_shared_boundary_element_face_index[iproc].push_back(face_index);
21906 if (Print_timings_level_load_balance>1)
21908 oomph_info <<
"CPU for sorting shared boundaries (load balance) [8]: "
21909 <<TimingHelpers::timer()-tt_start_sort_shared_boundaries
21930 double tt_start_create_new_shared_boundaries=0.0;
21931 if (Print_timings_level_load_balance>1)
21933 tt_start_create_new_shared_boundaries=TimingHelpers::timer();
21944 std::set<FiniteElement*> element_in_processor_pt;
21948 unsigned nh_count6 = 0;
21949 for (
unsigned e = 0; e < nelement_before_load_balance; e++)
21952 FiniteElement* ele_pt = backed_up_ele_pt[e];
21954 if (!(ele_pt->is_halo()))
21957 if (target_domain_for_local_non_halo_element[nh_count6++] == my_rank)
21960 element_in_processor_pt.insert(ele_pt);
21970 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21973 if (iproc != my_rank)
21977 const unsigned n_received_ele = received_elements_pt[iproc].size();
21978 for (
unsigned ie = 0; ie < n_received_ele; ie++)
21981 FiniteElement* ele_pt = received_elements_pt[iproc][ie];
21984 element_in_processor_pt.insert(ele_pt);
21993 create_new_shared_boundaries(element_in_processor_pt,
21994 new_shared_boundary_element_pt,
21995 new_shared_boundary_element_face_index);
21998 if (Print_timings_level_load_balance>1)
22000 oomph_info <<
"CPU for creating new shared boundaries (load balance) [9]: "
22001 <<TimingHelpers::timer()-tt_start_create_new_shared_boundaries
22023 double tt_start_delete_elements=0.0;
22024 if (Print_timings_level_load_balance>1)
22026 tt_start_delete_elements=TimingHelpers::timer();
22037 this->Halo_node_pt.clear();
22038 this->Root_halo_element_pt.clear();
22040 this->Haloed_node_pt.clear();
22041 this->Root_haloed_element_pt.clear();
22044 const unsigned nnodes = this->nnode();
22045 for (
unsigned j = 0; j < nnodes; j++)
22047 this->node_pt(j)->set_obsolete();
22051 this->flush_element_storage();
22054 this->delete_all_external_storage();
22057 this->External_halo_node_pt.clear();
22058 this->External_halo_element_pt.clear();
22060 this->External_haloed_node_pt.clear();
22061 this->External_haloed_element_pt.clear();
22064 Vector<FiniteElement*> deleted_elements;
22067 unsigned nh_count7 = 0;
22068 for (
unsigned e = 0; e < nelement_before_load_balance; e++)
22070 FiniteElement* ele_pt = backed_up_ele_pt[e];
22072 if (!(ele_pt->is_halo()))
22074 if (target_domain_for_local_non_halo_element[nh_count7++] == my_rank)
22077 this->add_element_pt(ele_pt);
22079 const unsigned nele_nodes = ele_pt->nnode();
22081 for (
unsigned j = 0; j < nele_nodes; j++)
22084 ele_pt->node_pt(j)->set_non_obsolete();
22091 deleted_elements.push_back(ele_pt);
22101 deleted_elements.push_back(ele_pt);
22110 for (
unsigned iproc = 0; iproc < nproc; iproc++)
22112 if (iproc != my_rank)
22116 const unsigned nreceived_ele = received_elements_pt[iproc].size();
22117 for (
unsigned ie = 0; ie < nreceived_ele; ie++)
22120 FiniteElement* ele_pt = received_elements_pt[iproc][ie];
22122 this->add_element_pt(ele_pt);
22124 const unsigned nele_nodes = ele_pt->nnode();
22126 for (
unsigned j = 0; j < nele_nodes; j++)
22129 ele_pt->node_pt(j)->set_non_obsolete();
22139 this->prune_dead_nodes();
22142 if (Print_timings_level_load_balance>1)
22144 oomph_info <<
"CPU for deleting elements no longer belonging to this processor (load balance) [10]: "
22145 <<TimingHelpers::timer()-tt_start_delete_elements
22163 double tt_start_re_etablish_halo_ed_info=0.0;
22164 if (Print_timings_level_load_balance>1)
22166 tt_start_re_etablish_halo_ed_info=TimingHelpers::timer();
22173 this->sort_nodes_on_shared_boundaries();
22180 const unsigned tmp_nboundary = this->nboundary();
22181 Vector<unsigned> ntmp_boundary_elements(tmp_nboundary);
22184 Vector<Vector<unsigned> > ntmp_boundary_elements_in_region(tmp_nboundary);
22186 const unsigned n_regions = this->nregion();
22189 for (
unsigned ib = 0; ib < tmp_nboundary; ib++)
22192 ntmp_boundary_elements[ib] = this->nboundary_element(ib);
22195 ntmp_boundary_elements_in_region[ib].resize(n_regions);
22198 for (
unsigned rr = 0 ; rr < n_regions; rr++)
22201 const unsigned region_id =
22202 static_cast<unsigned>(this->region_attribute(rr));
22207 ntmp_boundary_elements_in_region[ib][rr] =
22208 this->nboundary_element_in_region(ib, region_id);
22215 this->reset_halo_haloed_scheme();
22218 const unsigned nelement_after_load_balance = this->nelement();
22222 this->reset_boundary_element_info(ntmp_boundary_elements,
22223 ntmp_boundary_elements_in_region,
22249 for (
unsigned b = 0; b < tmp_nboundary; b++)
22251 if (this->boundary_geom_object_pt(b)!=0)
22254 this->flush_boundary_segment_node(b);
22257 Vector<Vector<Node*> > dummy_segment_node_pt;
22260 get_boundary_segment_nodes_helper(b, dummy_segment_node_pt);
22263 const unsigned nsegments = dummy_segment_node_pt.size();
22267 this->set_nboundary_segment_node(b, nsegments);
22273 if (Print_timings_level_load_balance>1)
22275 oomph_info <<
"CPU for re-establishing halo(ed) information (load balance) [11]: "
22276 <<TimingHelpers::timer()-tt_start_re_etablish_halo_ed_info
22287 if (Print_timings_level_load_balance>1)
22289 oomph_info <<
"CPU for load balance [n_ele_before="
22290 <<nelement_before_load_balance<<
", n_ele_after="
22291 <<nelement_after_load_balance<<
"]: "
22292 <<TimingHelpers::timer()-t_start_overall_load_balance
22296 oomph_info <<
"Load balance (unstructured mesh) [END]" << std::endl;
22305 template <
class ELEMENT>
22308 const Vector<FiniteElement*> &first_element_pt,
22309 const Vector<FiniteElement*> &second_element_pt,
22310 Vector<FiniteElement*> &first_shared_boundary_element_pt,
22311 Vector<unsigned> &first_shared_boundary_element_face_index,
22312 Vector<FiniteElement*> &second_shared_boundary_element_pt,
22313 Vector<unsigned> &second_shared_boundary_element_face_index)
22321 const unsigned nfirst_element = first_element_pt.size();
22323 for (
unsigned ef = 0; ef < nfirst_element; ef++)
22326 FiniteElement* fele_pt = first_element_pt[ef];
22328 bool first_ele_is_halo =
false;
22329 if (fele_pt->is_halo())
22331 first_ele_is_halo =
true;
22334 for (
unsigned ifface = 0; ifface < 3; ifface++)
22336 Vector<Node*> first_face(2);
22339 first_face[0] = fele_pt->node_pt(1);
22340 first_face[1] = fele_pt->node_pt(2);
22342 else if (ifface == 1)
22344 first_face[0] = fele_pt->node_pt(2);
22345 first_face[1] = fele_pt->node_pt(0);
22347 else if (ifface == 2)
22349 first_face[0] = fele_pt->node_pt(0);
22350 first_face[1] = fele_pt->node_pt(1);
22357 const unsigned nsecond_element = second_element_pt.size();
22359 for (
unsigned es = 0; es < nsecond_element; es++)
22362 FiniteElement* sele_pt = second_element_pt[es];
22364 bool second_ele_is_halo =
false;
22365 if (sele_pt->is_halo())
22367 second_ele_is_halo =
true;
22374 if (!(first_ele_is_halo && second_ele_is_halo))
22377 for (
unsigned isface = 0; isface < 3; isface++)
22379 Vector<Node*> second_face(2);
22382 second_face[0] = sele_pt->node_pt(1);
22383 second_face[1] = sele_pt->node_pt(2);
22385 else if (isface == 1)
22387 second_face[0] = sele_pt->node_pt(2);
22388 second_face[1] = sele_pt->node_pt(0);
22390 else if (isface == 2)
22392 second_face[0] = sele_pt->node_pt(0);
22393 second_face[1] = sele_pt->node_pt(1);
22398 if (first_face[0] == second_face[0] &&
22399 first_face[1] == second_face[1])
22402 first_shared_boundary_element_pt.push_back(fele_pt);
22404 first_shared_boundary_element_face_index.push_back(ifface);
22407 second_shared_boundary_element_pt.push_back(sele_pt);
22409 second_shared_boundary_element_face_index.push_back(isface);
22417 es = nsecond_element;
22421 else if (first_face[0] == second_face[1] &&
22422 first_face[1] == second_face[0])
22425 first_shared_boundary_element_pt.push_back(fele_pt);
22427 first_shared_boundary_element_face_index.push_back(ifface);
22430 second_shared_boundary_element_pt.push_back(sele_pt);
22432 second_shared_boundary_element_face_index.push_back(isface);
22440 es = nsecond_element;
22460 template <
class ELEMENT>
22463 &element_in_processor_pt,
22464 Vector<Vector<FiniteElement*> >
22465 &new_shared_boundary_element_pt,
22466 Vector<Vector<unsigned> >
22467 &new_shared_boundary_element_face_index)
22470 const unsigned nproc = this->communicator_pt()->nproc();
22472 const unsigned my_rank = this->communicator_pt()->my_rank();
22482 double tt_start_get_edges_from_shd_bnd_face_ele=0.0;
22483 if (Print_timings_level_load_balance>2)
22485 tt_start_get_edges_from_shd_bnd_face_ele=TimingHelpers::timer();
22489 Vector<Vector<FiniteElement*> > tmp_unsorted_face_ele_pt(nproc);
22491 Vector<Vector<FiniteElement*> > tmp_unsorted_ele_pt(nproc);
22494 Vector<Vector<int> > tmp_unsorted_face_index_ele(nproc);
22498 std::map<std::pair<Node*, Node*>,
unsigned> elements_edges_on_boundary;
22501 this->get_element_edges_on_boundary(elements_edges_on_boundary);
22504 std::map<std::pair<Node*,Node*>,
bool> overlapped_edge;
22510 Vector<Vector<int> > tmp_edge_boundary(nproc);
22514 for (
unsigned iproc = 0; iproc < nproc; iproc++)
22517 if (iproc != my_rank)
22521 const unsigned n_shared_bound_ele =
22522 new_shared_boundary_element_pt[iproc].size();
22526 Vector<std::pair<Node*, Node*> > done_faces;
22529 unsigned nrepeated_faces = 0;
22533 for (
unsigned iele = 0; iele < n_shared_bound_ele; iele++)
22536 FiniteElement* bulk_ele_pt =
22537 new_shared_boundary_element_pt[iproc][iele];
22541 static_cast<int>(new_shared_boundary_element_face_index[iproc][iele]);
22544 FiniteElement* tmp_ele_pt =
22545 new DummyFaceElement<ELEMENT> (bulk_ele_pt, face_index);
22549 bool done_face =
false;
22553 const unsigned nnode_face_ele = tmp_ele_pt->nnode();
22554 Node* first_face_node_pt = tmp_ele_pt->node_pt(0);
22555 Node* last_face_node_pt = tmp_ele_pt->node_pt(nnode_face_ele - 1);
22558 const unsigned ndone_faces = done_faces.size();
22560 for (
unsigned n = 0; n < ndone_faces; n++)
22562 Node* first_done_face_node_pt = done_faces[n].first;
22563 Node* second_done_face_node_pt = done_faces[n].second;
22564 if (first_face_node_pt == first_done_face_node_pt &&
22565 last_face_node_pt == second_done_face_node_pt)
22572 else if (first_face_node_pt == second_done_face_node_pt &&
22573 last_face_node_pt == first_done_face_node_pt)
22586 tmp_unsorted_face_ele_pt[iproc].push_back(tmp_ele_pt);
22588 tmp_unsorted_ele_pt[iproc].push_back(bulk_ele_pt);
22590 tmp_unsorted_face_index_ele[iproc].push_back(face_index);
22592 std::pair<Node*, Node*> tmp_edge =
22593 std::make_pair(first_face_node_pt, last_face_node_pt);
22595 done_faces.push_back(tmp_edge);
22599 int edge_boundary_id = -1;
22600 std::map<std::pair<Node*,Node*>,
unsigned >::iterator it;
22601 it = elements_edges_on_boundary.find(tmp_edge);
22604 if (it != elements_edges_on_boundary.end())
22608 edge_boundary_id = (*it).second;
22610 overlapped_edge[tmp_edge] =
true;
22612 std::pair<Node*, Node*> rev_tmp_edge =
22613 std::make_pair(last_face_node_pt, first_face_node_pt);
22615 overlapped_edge[rev_tmp_edge] =
true;
22620 std::pair<Node*,Node*> rtmp_edge =
22621 std::make_pair(last_face_node_pt, first_face_node_pt);
22622 it = elements_edges_on_boundary.find(rtmp_edge);
22623 if (it != elements_edges_on_boundary.end())
22627 edge_boundary_id = (*it).second;
22629 overlapped_edge[rtmp_edge] =
true;
22632 overlapped_edge[tmp_edge] =
true;
22636 tmp_edge_boundary[iproc].push_back(edge_boundary_id);
22652 if (Print_timings_level_load_balance>2)
22654 oomph_info <<
"CPU for getting edges from shared boundary face elements (load balance) [9.1]: "
22655 <<TimingHelpers::timer()-tt_start_get_edges_from_shd_bnd_face_ele
22676 double tt_start_sort_shared_face_elements=0.0;
22677 if (Print_timings_level_load_balance>2)
22679 tt_start_sort_shared_face_elements=TimingHelpers::timer();
22688 Vector<Vector<FiniteElement*> > unsorted_face_ele_pt(nproc);
22690 Vector<Vector<FiniteElement*> > unsorted_ele_pt(nproc);
22693 Vector<Vector<int> > unsorted_face_index_ele(nproc);
22697 Vector<Vector<int> > edge_boundary(nproc);
22703 std::vector<std::vector<bool> > tmp_treat_as_inverted(nproc);
22706 std::vector<std::vector<bool> > treat_as_inverted(nproc);
22712 for (
unsigned iproc = 0; iproc < nproc; iproc++)
22715 if (iproc != my_rank)
22718 const unsigned n_face_ele = tmp_unsorted_face_ele_pt[iproc].size();
22721 Vector<Vector<double> > centroid_vertices(n_face_ele);
22725 tmp_treat_as_inverted[iproc].resize(n_face_ele);
22729 for (
unsigned e = 0; e < n_face_ele; e++)
22732 FiniteElement* face_ele_pt = tmp_unsorted_face_ele_pt[iproc][e];
22734 const unsigned n_node = face_ele_pt->nnode();
22735 Vector<double> bottom_left(2);
22738 Node* node_pt = face_ele_pt->node_pt(0);
22739 bottom_left[0] = node_pt->x(0);
22740 bottom_left[1] = node_pt->x(1);
22742 tmp_treat_as_inverted[iproc][e] =
false;
22745 for (
unsigned n = 1; n < n_node; n++)
22748 Node* node_pt = face_ele_pt->node_pt(n);
22749 if (node_pt->x(1) < bottom_left[1])
22751 bottom_left[0] = node_pt->x(0);
22752 bottom_left[1] = node_pt->x(1);
22755 tmp_treat_as_inverted[iproc][e] =
true;
22757 else if (node_pt->x(1) == bottom_left[1])
22759 if (node_pt->x(0) < bottom_left[0])
22761 bottom_left[0] = node_pt->x(0);
22762 bottom_left[1] = node_pt->x(1);
22765 tmp_treat_as_inverted[iproc][e] =
true;
22772 centroid_vertices[e].resize(2);
22774 centroid_vertices[e][0] =
22775 (face_ele_pt->node_pt(0)->x(0) +
22776 face_ele_pt->node_pt(n_node-1)->x(0))*0.5;
22777 centroid_vertices[e][1] =
22778 (face_ele_pt->node_pt(0)->x(1) +
22779 face_ele_pt->node_pt(n_node-1)->x(1))*0.5;
22784 unsigned n_sorted_bottom_left = 0;
22786 std::vector<bool> done_face(n_face_ele,
false);
22789 while (n_sorted_bottom_left < n_face_ele)
22792 unsigned index = 0;
22793 Vector<double> current_bottom_left(2);
22794 for (
unsigned e = 0; e < n_face_ele; e++)
22800 current_bottom_left[0] = centroid_vertices[e][0];
22801 current_bottom_left[1] = centroid_vertices[e][1];
22811 for (
unsigned e = index + 1; e < n_face_ele; e++)
22816 if (centroid_vertices[e][1] < current_bottom_left[1])
22819 current_bottom_left[0] = centroid_vertices[e][0];
22820 current_bottom_left[1] = centroid_vertices[e][1];
22824 else if (centroid_vertices[e][1] == current_bottom_left[1])
22826 if (centroid_vertices[e][0] < current_bottom_left[0])
22829 current_bottom_left[0] = centroid_vertices[e][0];
22830 current_bottom_left[1] = centroid_vertices[e][1];
22842 unsorted_face_ele_pt[iproc].
22843 push_back(tmp_unsorted_face_ele_pt[iproc][index]);
22845 unsorted_ele_pt[iproc].
22846 push_back(tmp_unsorted_ele_pt[iproc][index]);
22848 unsorted_face_index_ele[iproc].
22849 push_back(tmp_unsorted_face_index_ele[iproc][index]);
22851 edge_boundary[iproc].
22852 push_back(tmp_edge_boundary[iproc][index]);
22854 treat_as_inverted[iproc].
22855 push_back(tmp_treat_as_inverted[iproc][index]);
22858 done_face[index] =
true;
22861 n_sorted_bottom_left++;
22868 const unsigned tmp_n_face_ele = unsorted_face_ele_pt[iproc].size();
22870 if (tmp_n_face_ele != n_face_ele)
22872 std::ostringstream error_stream;
22874 <<
"The number of face elements before sorting them starting\n"
22875 <<
"from their bottom-left vertex is different from the number\n"
22876 <<
"of face elements after the sorting\n"
22877 <<
"N. ele before sorting: (" << n_face_ele <<
")\n"
22878 <<
"N. ele after sorting: (" << tmp_n_face_ele <<
")\n";
22879 throw OomphLibError(error_stream.str(),
22880 "RefineableTriangleMesh::create_new_shared_boundaries()",
22881 OOMPH_EXCEPTION_LOCATION);
22890 if (Print_timings_level_load_balance>2)
22892 oomph_info <<
"CPU for sorting shared boundary face elements (load balance) [9.2]: "
22893 <<TimingHelpers::timer()-tt_start_sort_shared_face_elements
22915 double tt_start_compute_valency_of_nodes=0.0;
22916 if (Print_timings_level_load_balance>2)
22918 tt_start_compute_valency_of_nodes=TimingHelpers::timer();
22922 std::map<Node*, unsigned> global_node_degree;
22925 compute_shared_node_degree_helper(unsorted_face_ele_pt,
22926 global_node_degree);
22929 if (Print_timings_level_load_balance>2)
22931 oomph_info <<
"CPU for computing the valency of nodes (load balance) [9.3]: "
22932 <<TimingHelpers::timer()-tt_start_compute_valency_of_nodes
22950 double tt_start_nodes_on_non_overlapped_shd_bnd=0.0;
22951 if (Print_timings_level_load_balance>2)
22953 tt_start_nodes_on_non_overlapped_shd_bnd=TimingHelpers::timer();
22958 std::map<unsigned, std::map<Node*, bool> >
22959 node_on_bnd_not_overlapped_by_shd_bnd;
22962 for (std::map<std::pair<Node*,Node*>,
unsigned>::iterator it_map =
22963 elements_edges_on_boundary.begin();
22964 it_map != elements_edges_on_boundary.end(); it_map++)
22967 std::pair<Node*,Node*> edge_pair = (*it_map).first;
22969 if (!overlapped_edge[edge_pair])
22973 unsigned b = (*it_map).second;
22976 Node* left_node_pt = edge_pair.first;
22977 node_on_bnd_not_overlapped_by_shd_bnd[b][left_node_pt] =
true;
22980 Node* right_node_pt = edge_pair.second;
22981 node_on_bnd_not_overlapped_by_shd_bnd[b][right_node_pt] =
true;
22989 if (Print_timings_level_load_balance>2)
22991 oomph_info <<
"CPU for computing nodes on non overlapped shared boundaries (load balance) [9.4]: "
22992 <<TimingHelpers::timer()-tt_start_nodes_on_non_overlapped_shd_bnd
23015 double tt_start_join_shd_bnd_face_ele=0.0;
23016 if (Print_timings_level_load_balance>2)
23018 tt_start_join_shd_bnd_face_ele=TimingHelpers::timer();
23022 Vector<Vector<Vector<FiniteElement*> > > sorted_face_ele_pt(nproc);
23025 Vector<Vector<Vector<FiniteElement*> > > sorted_ele_pt(nproc);
23029 Vector<Vector<Vector<int> > > sorted_face_index_ele(nproc);
23035 Vector<Vector<int> > edge_boundary_id(nproc);
23039 Vector<Vector<Vector<int> > > sorted_connection_info(nproc);
23044 Vector<Vector<unsigned> > proc_local_shared_boundary_id(nproc);
23048 std::map<unsigned, std::list<Node*> >
23049 local_shd_bnd_id_to_sorted_list_node_pt;
23054 unsigned local_shd_bnd_id = this->Initial_shared_boundary_id;
23059 std::map<FiniteElement*, bool> done_ele;
23062 std::map<FiniteElement*, bool> is_inverted;
23066 for (
unsigned iproc = 0; iproc < nproc; iproc++)
23069 if (iproc != my_rank)
23073 const unsigned nunsorted_face_ele =
23074 unsorted_face_ele_pt[iproc].size();
23076 unsigned nsorted_face_ele = 0;
23079 while (nsorted_face_ele < nunsorted_face_ele)
23088 bool found_root_element =
false;
23092 unsigned root_index = 0;
23095 std::list<FiniteElement*> tmp_sorted_face_ele_pt;
23098 std::list<FiniteElement*> tmp_sorted_ele_pt;
23102 std::list<int> tmp_sorted_face_index_ele;
23107 std::list<Node*> tmp_sorted_nodes_pt;
23109 tmp_sorted_nodes_pt.clear();
23112 Node* initial_node_pt = 0;
23113 Node* final_node_pt = 0;
23117 int root_edge_bound_id = -1;
23121 for (
unsigned e = 0; e < nunsorted_face_ele; e++)
23124 FiniteElement* root_ele_pt = unsorted_face_ele_pt[iproc][e];
23126 if (!done_ele[root_ele_pt])
23130 root_edge_bound_id = edge_boundary[iproc][e];
23133 tmp_sorted_face_ele_pt.push_back(root_ele_pt);
23135 tmp_sorted_ele_pt.push_back(unsorted_ele_pt[iproc][e]);
23138 tmp_sorted_face_index_ele.push_back(
23139 unsorted_face_index_ele[iproc][e]);
23142 const unsigned nnodes = root_ele_pt->nnode();
23144 if (!treat_as_inverted[iproc][e])
23146 initial_node_pt = root_ele_pt->node_pt(0);
23147 final_node_pt = root_ele_pt->node_pt(nnodes-1);
23151 initial_node_pt = root_ele_pt->node_pt(nnodes-1);
23152 final_node_pt = root_ele_pt->node_pt(0);
23155 tmp_sorted_nodes_pt.push_back(initial_node_pt);
23156 tmp_sorted_nodes_pt.push_back(final_node_pt);
23159 done_ele[root_ele_pt] =
true;
23161 if (!treat_as_inverted[iproc][e])
23164 is_inverted[root_ele_pt] =
false;
23169 is_inverted[root_ele_pt] =
true;
23172 nsorted_face_ele++;
23177 found_root_element =
true;
23187 if (!found_root_element)
23189 std::ostringstream error_stream;
23191 <<
"It was not possible the found the root element\n\n";
23192 throw OomphLibError(error_stream.str(),
23193 OOMPH_CURRENT_FUNCTION,
23194 OOMPH_EXCEPTION_LOCATION);
23202 bool new_element_added =
true;
23212 bool element_added_to_the_left =
false;
23213 bool element_added_to_the_right =
false;
23217 bool connection_to_the_left =
false;
23221 bool connection_to_the_right =
false;
23226 bool current_polyline_has_connections_at_both_ends =
false;
23238 int bound_id_connection_to_the_left = -1;
23239 int bound_id_connection_to_the_right = -1;
23243 const unsigned initial_node_degree =
23244 global_node_degree[initial_node_pt];
23248 const bool called_for_load_balance=
true;
23252 bound_id_connection_to_the_left =
23253 this->check_connections_of_polyline_nodes(
23254 element_in_processor_pt,
23255 root_edge_bound_id,
23257 node_on_bnd_not_overlapped_by_shd_bnd,
23258 tmp_sorted_nodes_pt,
23259 local_shd_bnd_id_to_sorted_list_node_pt,
23260 initial_node_degree,
23262 called_for_load_balance);
23266 if (bound_id_connection_to_the_left != -1)
23268 connection_to_the_left =
true;
23273 const unsigned final_node_degree =
23274 global_node_degree[final_node_pt];
23277 bound_id_connection_to_the_right =
23278 this->check_connections_of_polyline_nodes(
23279 element_in_processor_pt,
23280 root_edge_bound_id,
23282 node_on_bnd_not_overlapped_by_shd_bnd,
23283 tmp_sorted_nodes_pt,
23284 local_shd_bnd_id_to_sorted_list_node_pt,
23287 called_for_load_balance);
23291 if (bound_id_connection_to_the_right != -1)
23293 connection_to_the_right =
true;
23298 if (connection_to_the_left && connection_to_the_right)
23299 {current_polyline_has_connections_at_both_ends =
true;}
23307 while(new_element_added &&
23308 (nsorted_face_ele < nunsorted_face_ele)
23309 && !current_polyline_has_connections_at_both_ends)
23315 for (
unsigned e = root_index; e < nunsorted_face_ele; e++)
23318 new_element_added =
false;
23319 element_added_to_the_left =
false;
23320 element_added_to_the_right =
false;
23323 FiniteElement* tmp_ele_pt = unsorted_face_ele_pt[iproc][e];
23325 const int edge_bound_id = edge_boundary[iproc][e];
23329 if (!done_ele[tmp_ele_pt]
23330 && (edge_bound_id == root_edge_bound_id))
23333 const unsigned nnodes = tmp_ele_pt->nnode();
23336 Node* first_node_pt = 0;
23337 Node* last_node_pt = 0;
23338 if (!treat_as_inverted[iproc][e])
23340 first_node_pt = tmp_ele_pt->node_pt(0);
23341 last_node_pt = tmp_ele_pt->node_pt(nnodes-1);
23345 first_node_pt = tmp_ele_pt->node_pt(nnodes-1);
23346 last_node_pt = tmp_ele_pt->node_pt(0);
23352 Node* new_added_node_pt = 0;
23355 if (initial_node_pt == last_node_pt &&
23356 !connection_to_the_left)
23359 new_added_node_pt = initial_node_pt = first_node_pt;
23361 tmp_sorted_nodes_pt.push_front(first_node_pt);
23364 tmp_sorted_face_ele_pt.push_front(tmp_ele_pt);
23366 tmp_sorted_ele_pt.push_front(unsorted_ele_pt[iproc][e]);
23369 tmp_sorted_face_index_ele.push_front(
23370 unsorted_face_index_ele[iproc][e]);
23371 if (!treat_as_inverted[iproc][e])
23374 is_inverted[tmp_ele_pt] =
false;
23379 is_inverted[tmp_ele_pt] =
true;
23382 new_element_added =
true;
23385 element_added_to_the_left =
true;
23388 else if (initial_node_pt == first_node_pt &&
23389 !connection_to_the_left)
23392 new_added_node_pt = initial_node_pt = last_node_pt;
23394 tmp_sorted_nodes_pt.push_front(last_node_pt);
23397 tmp_sorted_face_ele_pt.push_front(tmp_ele_pt);
23399 tmp_sorted_ele_pt.push_front(unsorted_ele_pt[iproc][e]);
23402 tmp_sorted_face_index_ele.push_front(
23403 unsorted_face_index_ele[iproc][e]);
23404 if (!treat_as_inverted[iproc][e])
23407 is_inverted[tmp_ele_pt] =
true;
23412 is_inverted[tmp_ele_pt] =
false;
23415 new_element_added =
true;
23418 element_added_to_the_left =
true;
23421 else if (final_node_pt == first_node_pt
23422 && !connection_to_the_right)
23425 new_added_node_pt = final_node_pt = last_node_pt;
23427 tmp_sorted_nodes_pt.push_back(last_node_pt);
23430 tmp_sorted_face_ele_pt.push_back(tmp_ele_pt);
23432 tmp_sorted_ele_pt.push_back(unsorted_ele_pt[iproc][e]);
23435 tmp_sorted_face_index_ele.push_back(
23436 unsorted_face_index_ele[iproc][e]);
23437 if (!treat_as_inverted[iproc][e])
23440 is_inverted[tmp_ele_pt] =
false;
23445 is_inverted[tmp_ele_pt] =
true;
23448 new_element_added =
true;
23451 element_added_to_the_right =
true;
23454 else if (final_node_pt == last_node_pt &&
23455 !connection_to_the_right)
23458 new_added_node_pt = final_node_pt = first_node_pt;
23460 tmp_sorted_nodes_pt.push_back(first_node_pt);
23463 tmp_sorted_face_ele_pt.push_back(tmp_ele_pt);
23465 tmp_sorted_ele_pt.push_back(unsorted_ele_pt[iproc][e]);
23468 tmp_sorted_face_index_ele.push_back(
23469 unsorted_face_index_ele[iproc][e]);
23470 if (!treat_as_inverted[iproc][e])
23473 is_inverted[tmp_ele_pt] =
true;
23478 is_inverted[tmp_ele_pt] =
false;
23481 new_element_added =
true;
23484 element_added_to_the_right =
true;
23488 if (new_element_added)
23491 done_ele[tmp_ele_pt] =
true;
23493 nsorted_face_ele++;
23497 const unsigned new_added_node_degree =
23498 global_node_degree[new_added_node_pt];
23507 if (element_added_to_the_left && !connection_to_the_left)
23510 bound_id_connection_to_the_left =
23511 this->check_connections_of_polyline_nodes(
23512 element_in_processor_pt,
23513 root_edge_bound_id,
23515 node_on_bnd_not_overlapped_by_shd_bnd,
23516 tmp_sorted_nodes_pt,
23517 local_shd_bnd_id_to_sorted_list_node_pt,
23518 new_added_node_degree,
23520 called_for_load_balance);
23524 if (bound_id_connection_to_the_left != -1)
23526 connection_to_the_left =
true;
23536 if (element_added_to_the_right && !connection_to_the_right)
23539 bound_id_connection_to_the_right =
23540 this->check_connections_of_polyline_nodes(
23541 element_in_processor_pt,
23542 root_edge_bound_id,
23544 node_on_bnd_not_overlapped_by_shd_bnd,
23545 tmp_sorted_nodes_pt,
23546 local_shd_bnd_id_to_sorted_list_node_pt,
23547 new_added_node_degree,
23549 called_for_load_balance);
23553 if (bound_id_connection_to_the_right != -1)
23555 connection_to_the_right =
true;
23564 if (connection_to_the_left && connection_to_the_right)
23565 {current_polyline_has_connections_at_both_ends =
true;}
23588 Vector<FiniteElement*> tmp_vector_sorted_ele_pt;
23590 for (std::list<FiniteElement*>::iterator it =
23591 tmp_sorted_ele_pt.begin(); it != tmp_sorted_ele_pt.end(); it++)
23593 tmp_vector_sorted_ele_pt.push_back((*it));
23597 Vector<FiniteElement*> tmp_vector_sorted_face_ele_pt;
23600 for (std::list<FiniteElement*>::iterator it =
23601 tmp_sorted_face_ele_pt.begin();
23602 it != tmp_sorted_face_ele_pt.end(); it++)
23604 tmp_vector_sorted_face_ele_pt.push_back((*it));
23608 Vector<int> tmp_vector_sorted_face_index_ele;
23610 for (std::list<int>::iterator it =
23611 tmp_sorted_face_index_ele.begin();
23612 it != tmp_sorted_face_index_ele.end(); it++)
23614 tmp_vector_sorted_face_index_ele.push_back((*it));
23618 Vector<std::list<Node*> > final_sorted_nodes_pt;
23621 Vector<Vector<FiniteElement*> > final_boundary_element_pt;
23624 Vector<Vector<FiniteElement*> > final_boundary_face_element_pt;
23626 Vector<Vector<int> > final_face_index_element;
23629 Vector<int> final_bound_id_connection_to_the_left;
23632 Vector<int> final_bound_id_connection_to_the_right;
23635 this->break_loops_on_shared_polyline_load_balance_helper(
23637 tmp_sorted_nodes_pt,
23638 tmp_vector_sorted_ele_pt,
23639 tmp_vector_sorted_face_ele_pt, tmp_vector_sorted_face_index_ele,
23640 bound_id_connection_to_the_left, bound_id_connection_to_the_right,
23641 final_sorted_nodes_pt,
23642 final_boundary_element_pt,
23643 final_boundary_face_element_pt, final_face_index_element,
23644 final_bound_id_connection_to_the_left,
23645 final_bound_id_connection_to_the_right);
23648 const unsigned n_final_sorted_nodes = final_sorted_nodes_pt.size();
23651 for (
unsigned i = 0; i < n_final_sorted_nodes; i++)
23655 local_shd_bnd_id_to_sorted_list_node_pt[local_shd_bnd_id] =
23656 final_sorted_nodes_pt[i];
23660 proc_local_shared_boundary_id[iproc].push_back(local_shd_bnd_id);
23665 local_shd_bnd_id++;
23668 sorted_ele_pt[iproc].push_back(final_boundary_element_pt[i]);
23671 sorted_face_ele_pt[iproc].
23672 push_back(final_boundary_face_element_pt[i]);
23675 sorted_face_index_ele[iproc].push_back(final_face_index_element[i]);
23678 edge_boundary_id[iproc].push_back(root_edge_bound_id);
23684 Vector<int> bnd_connections_ids(2);
23685 bnd_connections_ids[0] = final_bound_id_connection_to_the_left[i];
23686 bnd_connections_ids[1] = final_bound_id_connection_to_the_right[i];
23687 sorted_connection_info[iproc].push_back(bnd_connections_ids);
23699 if (Print_timings_level_load_balance>2)
23701 oomph_info <<
"CPU for joining shared boundary face elements (load balance) [9.5]: "
23702 <<TimingHelpers::timer()-tt_start_join_shd_bnd_face_ele
23730 double tt_start_get_new_shared_boundaries_ids=0.0;
23731 if (Print_timings_level_load_balance>2)
23733 tt_start_get_new_shared_boundaries_ids=TimingHelpers::timer();
23737 Vector<unsigned> nshared_boundaries_with_processor(nproc);
23739 for (
unsigned iproc = 0; iproc < nproc; iproc++)
23742 if (iproc != my_rank)
23746 nshared_boundaries_with_processor[iproc] =
23747 sorted_face_ele_pt[iproc].size();
23757 const unsigned root_processor = 0;
23760 OomphCommunicator* comm_pt = this->communicator_pt();
23765 Vector<unsigned> flat_unsigned_root_received_data(nproc*nproc);
23768 MPI_Gather(&nshared_boundaries_with_processor[0],
23773 &flat_unsigned_root_received_data[0],
23781 comm_pt->mpi_comm());
23786 Vector<unsigned> flat_unsigned_root_send_receive_data;
23790 unsigned new_initial_shared_boundary_id = 0;
23791 unsigned new_final_shared_boundary_id = 0;
23794 if (my_rank == root_processor)
23798 Vector<Vector<unsigned> > root_nshared_bound_proc_with_proc(nproc);
23801 for (
unsigned iproc = 0; iproc < nproc; iproc++)
23804 root_nshared_bound_proc_with_proc[iproc].resize(nproc);
23807 for (
unsigned jproc = 0; jproc < nproc; jproc++)
23809 root_nshared_bound_proc_with_proc[iproc][jproc] =
23810 flat_unsigned_root_received_data[(iproc * nproc) + jproc];
23819 for (
unsigned iproc = 0; iproc < nproc; iproc++)
23821 for (
unsigned jproc = 0; jproc < iproc; jproc++)
23823 if (root_nshared_bound_proc_with_proc[iproc][jproc] !=
23824 root_nshared_bound_proc_with_proc[jproc][iproc])
23826 std::ostringstream error_stream;
23828 <<
"ROOT PROCESSOR ERROR\n\n"
23829 <<
"The number of shared boundaries between processor ("
23830 << iproc <<
") and (" << jproc <<
") is not the same:\n"
23831 <<
"Shared boundaries of processor (" << iproc
23832 <<
") with processor (" << jproc <<
"): ("
23833 << root_nshared_bound_proc_with_proc[iproc][jproc] <<
")\n"
23834 <<
"Shared boundaries of processor (" << jproc
23835 <<
") with processor (" << iproc <<
"): ("
23836 << root_nshared_bound_proc_with_proc[jproc][iproc] <<
")\n\n";
23837 throw OomphLibError(error_stream.str(),
23838 OOMPH_CURRENT_FUNCTION,
23839 OOMPH_EXCEPTION_LOCATION);
23855 Vector<Vector<unsigned> > start_shared_bound_id_proc_with_proc(nproc);
23858 for (
unsigned iproc = 0; iproc < nproc; iproc++)
23859 {start_shared_bound_id_proc_with_proc[iproc].resize(nproc);}
23863 unsigned shared_bound_id = this->nboundary();
23866 new_initial_shared_boundary_id = shared_bound_id;
23869 for (
unsigned iproc = 0; iproc < nproc; iproc++)
23871 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
23874 if (root_nshared_bound_proc_with_proc[iproc][jproc] > 0)
23878 start_shared_bound_id_proc_with_proc[iproc][jproc] = shared_bound_id;
23879 start_shared_bound_id_proc_with_proc[jproc][iproc] = shared_bound_id;
23883 shared_bound_id+= root_nshared_bound_proc_with_proc[iproc][jproc];
23891 new_final_shared_boundary_id = shared_bound_id;
23894 Vector<unsigned> send_start_shared_bound_id_proc_with_proc(nproc*nproc);
23898 for (
unsigned iproc = 0; iproc < nproc; iproc++)
23900 for (
unsigned jproc = 0; jproc < nproc; jproc++)
23904 const unsigned initial_shd_bnd_id =
23905 start_shared_bound_id_proc_with_proc[iproc][jproc];
23906 flat_unsigned_root_send_receive_data.push_back(initial_shd_bnd_id);
23910 const unsigned nshared_bnd_iproc_jproc =
23911 root_nshared_bound_proc_with_proc[iproc][jproc];
23912 flat_unsigned_root_send_receive_data.push_back(nshared_bnd_iproc_jproc);
23920 flat_unsigned_root_send_receive_data.
23921 push_back(new_initial_shared_boundary_id);
23924 flat_unsigned_root_send_receive_data.
23925 push_back(new_final_shared_boundary_id);
23936 unsigned root_ndata_sent_to_all_proc =
23937 flat_unsigned_root_send_receive_data.size();
23939 MPI_Bcast(&root_ndata_sent_to_all_proc,
23940 1, MPI_UNSIGNED, root_processor,
23941 comm_pt->mpi_comm());
23944 if (my_rank != root_processor)
23946 flat_unsigned_root_send_receive_data.resize(root_ndata_sent_to_all_proc);
23951 MPI_Bcast(&flat_unsigned_root_send_receive_data[0],
23954 root_ndata_sent_to_all_proc,
23958 comm_pt->mpi_comm());
23962 Vector<Vector<unsigned> > initial_shared_bound_id_proc_with_proc(nproc);
23968 Vector<Vector<unsigned> > nshared_bound_proc_with_proc(nproc);
23970 unsigned iflat_counter = 0;
23972 for (
unsigned iproc = 0; iproc < nproc; iproc++)
23975 initial_shared_bound_id_proc_with_proc[iproc].resize(nproc);
23976 nshared_bound_proc_with_proc[iproc].resize(nproc);
23979 for (
unsigned jproc = 0; jproc < nproc; jproc++)
23983 initial_shared_bound_id_proc_with_proc[iproc][jproc] =
23984 flat_unsigned_root_send_receive_data[iflat_counter++];
23988 nshared_bound_proc_with_proc[iproc][jproc] =
23989 flat_unsigned_root_send_receive_data[iflat_counter++];
23996 new_initial_shared_boundary_id =
23997 flat_unsigned_root_send_receive_data[root_ndata_sent_to_all_proc-2];
24000 new_final_shared_boundary_id =
24001 flat_unsigned_root_send_receive_data[root_ndata_sent_to_all_proc-1];
24004 if (Print_timings_level_load_balance>2)
24006 oomph_info <<
"CPU for computing new shared boundaries ids (load balance) [9.6]: "
24007 <<TimingHelpers::timer()-tt_start_get_new_shared_boundaries_ids
24028 double tt_start_create_new_shared_boundaries_polylines=0.0;
24029 if (Print_timings_level_load_balance>2)
24031 tt_start_create_new_shared_boundaries_polylines=TimingHelpers::timer();
24041 this->flush_shared_boundary_polyline_pt();
24042 this->Shared_boundary_polyline_pt.resize(nproc);
24045 this->Shared_boundaries_ids.clear();
24046 this->Shared_boundaries_ids.resize(nproc);
24047 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24049 this->Shared_boundaries_ids[iproc].clear();
24050 this->Shared_boundaries_ids[iproc].resize(nproc);
24054 this->Shared_boundary_from_processors.clear();
24055 this->Shared_boundary_overlaps_internal_boundary.clear();
24056 this->Boundary_was_splitted.clear();
24057 this->Boundary_subpolylines.clear();
24058 this->Boundary_marked_as_shared_boundary.clear();
24061 this->flush_shared_boundary_element();
24062 this->flush_face_index_at_shared_boundary();
24063 this->flush_shared_boundary_node();
24064 this->flush_sorted_shared_boundary_node();
24068 const unsigned old_local_shd_bnd_id = this->Initial_shared_boundary_id;
24071 this->Initial_shared_boundary_id = new_initial_shared_boundary_id;
24072 this->Final_shared_boundary_id = new_final_shared_boundary_id;
24076 Vector<TriangleMeshPolyLine *> unsorted_polylines_pt;
24082 std::map<unsigned, unsigned> local_to_global_shd_bnd_id;
24089 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24095 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
24100 if (iproc == my_rank || jproc == my_rank)
24103 unsigned ref_proc = 0;
24104 if (iproc == my_rank)
24105 {ref_proc = jproc;}
24106 else if (jproc == my_rank)
24107 {ref_proc = iproc;}
24111 const unsigned nshared_bound_iproc_jproc =
24112 nshared_bound_proc_with_proc[iproc][jproc];
24115 for (
unsigned counter = 0;
24116 counter < nshared_bound_iproc_jproc;
24120 const unsigned shd_bnd_id =
24121 initial_shared_bound_id_proc_with_proc[iproc][jproc] + counter;
24124 this->Shared_boundaries_ids[iproc][jproc].push_back(shd_bnd_id);
24125 this->Shared_boundaries_ids[jproc][iproc].push_back(shd_bnd_id);
24129 Vector<unsigned> processors(2);
24130 processors[0] = iproc;
24131 processors[1] = jproc;
24132 this->Shared_boundary_from_processors[shd_bnd_id] = processors;
24137 int root_edge_bound_id = edge_boundary_id[ref_proc][counter];
24140 if (root_edge_bound_id != -1)
24144 this->Shared_boundary_overlaps_internal_boundary[shd_bnd_id] =
24145 static_cast<unsigned>(root_edge_bound_id);
24152 Vector<Node*> node_pt_to_create_shared_polyline;
24157 FiniteElement* first_face_ele_pt =
24158 sorted_face_ele_pt[ref_proc][counter][0];
24161 const unsigned first_face_ele_nnodes = first_face_ele_pt->nnode();
24162 if (!is_inverted[first_face_ele_pt])
24165 Node* first_node_pt = first_face_ele_pt->node_pt(0);
24167 node_pt_to_create_shared_polyline.push_back(first_node_pt);
24169 this->add_shared_boundary_node(shd_bnd_id, first_node_pt);
24174 Node* first_node_pt =
24175 first_face_ele_pt->node_pt(first_face_ele_nnodes - 1);
24177 node_pt_to_create_shared_polyline.push_back(first_node_pt);
24179 this->add_shared_boundary_node(shd_bnd_id, first_node_pt);
24187 const unsigned nshared_boundary_elements =
24188 sorted_face_ele_pt[ref_proc][counter].size();
24192 for (
unsigned ie = 0 ; ie < nshared_boundary_elements; ie++)
24195 FiniteElement* bulk_ele_pt = sorted_ele_pt[ref_proc][counter][ie];
24199 this->add_shared_boundary_element(shd_bnd_id,
24204 const int face_index =
24205 sorted_face_index_ele[ref_proc][counter][ie];
24209 this->add_face_index_at_shared_boundary(shd_bnd_id,
24213 FiniteElement* face_ele_pt =
24214 sorted_face_ele_pt[ref_proc][counter][ie];
24217 const unsigned nnodes = face_ele_pt->nnode();
24218 if (!is_inverted[face_ele_pt])
24222 for (
unsigned n = 1; n < nnodes; n++)
24225 Node* node_pt = face_ele_pt->node_pt(n);
24227 this->add_shared_boundary_node(shd_bnd_id, node_pt);
24233 Node* last_node_pt = face_ele_pt->node_pt(nnodes - 1);
24234 node_pt_to_create_shared_polyline.push_back(last_node_pt);
24240 for (
int n = nnodes-2; n >= 0; n--)
24243 Node* node_pt = face_ele_pt->node_pt(n);
24245 this->add_shared_boundary_node(shd_bnd_id, node_pt);
24251 Node* last_node_pt = face_ele_pt->node_pt(0);
24252 node_pt_to_create_shared_polyline.push_back(last_node_pt);
24259 const unsigned nnodes_to_create_shared_boundary =
24260 node_pt_to_create_shared_polyline.size();
24263 Vector<Vector<double> > vertices(nnodes_to_create_shared_boundary);
24264 for (
unsigned n = 0; n < nnodes_to_create_shared_boundary; n++)
24266 vertices[n].resize(2);
24268 Node* tmp_node_pt = node_pt_to_create_shared_polyline[n];
24270 vertices[n][0] = tmp_node_pt->x(0);
24271 vertices[n][1] = tmp_node_pt->x(1);
24275 TriangleMeshPolyLine *polyline_pt =
24276 new TriangleMeshPolyLine(vertices, shd_bnd_id);
24279 this->Boundary_curve_section_pt[shd_bnd_id] = polyline_pt;
24283 unsorted_polylines_pt.push_back(polyline_pt);
24286 this->Free_curve_section_pt.insert(polyline_pt);
24292 const unsigned local_shd_bnd_id =
24293 proc_local_shared_boundary_id[ref_proc][counter];
24297 local_to_global_shd_bnd_id[local_shd_bnd_id] = shd_bnd_id;
24304 int tmp_bnd_id_connection_to_the_left =
24305 sorted_connection_info[ref_proc][counter][0];
24307 int tmp_bnd_id_connection_to_the_right =
24308 sorted_connection_info[ref_proc][counter][1];
24312 int bnd_id_connection_to_the_left = -1;
24313 int bnd_id_connection_to_the_right = -1;
24320 if (tmp_bnd_id_connection_to_the_left == -2)
24323 bnd_id_connection_to_the_left = shd_bnd_id;
24327 if (tmp_bnd_id_connection_to_the_left == -3)
24330 bnd_id_connection_to_the_left = -1;
24335 if (tmp_bnd_id_connection_to_the_left >=
24336 static_cast<int>(old_local_shd_bnd_id))
24341 std::map<unsigned, unsigned>::iterator it =
24342 local_to_global_shd_bnd_id.find(
24343 static_cast<unsigned>(tmp_bnd_id_connection_to_the_left));
24346 if (it==local_to_global_shd_bnd_id.end())
24348 std::stringstream error_message;
24350 <<
"The global shared boundary id was not found for\n"
24351 <<
"the local shared boundary shared with processor ("
24352 << ref_proc <<
").\n"
24353 <<
"This processor: (" << my_rank <<
")\n"
24354 <<
"Boundary shared with processor: (" << ref_proc <<
")\n"
24355 <<
"Local shared boundary: ("
24356 << tmp_bnd_id_connection_to_the_left <<
")\n";
24357 throw OomphLibError(error_message.str(),
24358 OOMPH_CURRENT_FUNCTION,
24359 OOMPH_EXCEPTION_LOCATION);
24364 bnd_id_connection_to_the_left =
24365 local_to_global_shd_bnd_id[
24366 static_cast<unsigned>(tmp_bnd_id_connection_to_the_left)];
24373 bnd_id_connection_to_the_left =
24374 tmp_bnd_id_connection_to_the_left;
24383 if (tmp_bnd_id_connection_to_the_right == -2)
24386 bnd_id_connection_to_the_right = shd_bnd_id;
24390 if (tmp_bnd_id_connection_to_the_right == -3)
24393 bnd_id_connection_to_the_right = -1;
24398 if (tmp_bnd_id_connection_to_the_right >=
24399 static_cast<int>(old_local_shd_bnd_id))
24404 std::map<unsigned, unsigned>::iterator it =
24405 local_to_global_shd_bnd_id.find(
24406 static_cast<unsigned>(tmp_bnd_id_connection_to_the_right));
24409 if (it==local_to_global_shd_bnd_id.end())
24411 std::stringstream error_message;
24413 <<
"The global shared boundary id was not found for\n"
24414 <<
"the local shared boundary shared with processor ("
24415 << ref_proc <<
").\n"
24416 <<
"This processor: (" << my_rank <<
")\n"
24417 <<
"Boundary shared with processor: (" << ref_proc <<
")\n"
24418 <<
"Local shared boundary: ("
24419 << tmp_bnd_id_connection_to_the_right <<
")\n";
24420 throw OomphLibError(error_message.str(),
24421 OOMPH_CURRENT_FUNCTION,
24422 OOMPH_EXCEPTION_LOCATION);
24426 bnd_id_connection_to_the_right =
24427 local_to_global_shd_bnd_id[
24428 static_cast<unsigned>(tmp_bnd_id_connection_to_the_right)];
24435 bnd_id_connection_to_the_right =
24436 tmp_bnd_id_connection_to_the_right;
24442 if (bnd_id_connection_to_the_left != -1)
24445 const unsigned ubnd_id_connection_to_the_left =
24446 static_cast<unsigned>(bnd_id_connection_to_the_left);
24448 polyline_pt->set_initial_vertex_connected();
24450 polyline_pt->initial_vertex_connected_bnd_id() =
24451 ubnd_id_connection_to_the_left;
24453 polyline_pt->initial_vertex_connected_n_chunk() = 0;
24459 if (bnd_id_connection_to_the_right != -1)
24463 const unsigned ubnd_id_connection_to_the_right =
24464 static_cast<unsigned>(bnd_id_connection_to_the_right);
24466 polyline_pt->set_final_vertex_connected();
24468 polyline_pt->final_vertex_connected_bnd_id() =
24469 ubnd_id_connection_to_the_right;
24471 polyline_pt->final_vertex_connected_n_chunk() = 0;
24485 const unsigned nshared_bound_iproc_jproc =
24486 nshared_bound_proc_with_proc[iproc][jproc];
24488 for (
unsigned counter = 0;
24489 counter < nshared_bound_iproc_jproc;
24493 const unsigned shd_bnd_id =
24494 initial_shared_bound_id_proc_with_proc[iproc][jproc] + counter;
24497 this->Shared_boundaries_ids[iproc][jproc].push_back(shd_bnd_id);
24498 this->Shared_boundaries_ids[jproc][iproc].push_back(shd_bnd_id);
24502 Vector<unsigned> processors(2);
24503 processors[0] = iproc;
24504 processors[1] = jproc;
24505 this->Shared_boundary_from_processors[shd_bnd_id] = processors;
24516 if (Print_timings_level_load_balance>2)
24518 oomph_info <<
"CPU for creating new shared boundaries representations (load balance) [9.7]: "
24519 <<TimingHelpers::timer()-tt_start_create_new_shared_boundaries_polylines
24537 double tt_start_create_new_shared_curves=0.0;
24538 if (Print_timings_level_load_balance>2)
24540 tt_start_create_new_shared_curves=TimingHelpers::timer();
24545 if (unsorted_polylines_pt.size() > 0)
24549 this->sort_polylines_helper(unsorted_polylines_pt,
24550 this->Shared_boundary_polyline_pt[my_rank]);
24554 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24556 const unsigned nface_ele = unsorted_face_ele_pt[iproc].size();
24557 for (
unsigned e = 0; e < nface_ele; e++)
24559 delete unsorted_face_ele_pt[iproc][e];
24560 unsorted_face_ele_pt[iproc][e] = 0;
24566 if (Print_timings_level_load_balance>2)
24568 oomph_info <<
"CPU for creating the new shared curves (load balance) [9.8]: "
24569 <<TimingHelpers::timer()-tt_start_create_new_shared_curves
24587 template <
class ELEMENT>
24590 &unsorted_face_ele_pt,
24591 std::map<Node*, unsigned>
24592 &global_node_degree)
24595 const unsigned nproc = this->communicator_pt()->nproc();
24596 const unsigned my_rank = this->communicator_pt()->my_rank();
24600 Vector<Vector<Node*> > tmp_sorted_shared_node_pt(nproc);
24607 std::map<Node*, Vector<Vector<unsigned> > > node_alias;
24611 Vector<Vector<Vector<unsigned> > > local_adjacency_matrix(nproc);
24615 create_adjacency_matrix_new_shared_edges_helper(unsorted_face_ele_pt,
24616 tmp_sorted_shared_node_pt,
24618 local_adjacency_matrix);
24625 Vector<unsigned> package_unsigned_send_data_to_root;
24631 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24634 package_unsigned_send_data_to_root.push_back(iproc);
24637 const unsigned n_nodes = tmp_sorted_shared_node_pt[iproc].size();
24640 package_unsigned_send_data_to_root.push_back(n_nodes);
24643 for (
unsigned ishd = 0; ishd < n_nodes; ishd++)
24646 Node* shd_node_pt = tmp_sorted_shared_node_pt[iproc][ishd];
24649 Vector<Vector<unsigned> > alias_node_info = node_alias[shd_node_pt];
24652 const unsigned n_alias = alias_node_info.size();
24655 package_unsigned_send_data_to_root.push_back(n_alias);
24658 for (
unsigned i = 0; i < n_alias; i++)
24662 package_unsigned_send_data_to_root.push_back(alias_node_info[i][0]);
24664 package_unsigned_send_data_to_root.push_back(alias_node_info[i][1]);
24666 package_unsigned_send_data_to_root.push_back(alias_node_info[i][2]);
24672 for (
unsigned i = 0; i < n_nodes; i++)
24674 for (
unsigned j = 0; j < n_nodes; j++)
24677 package_unsigned_send_data_to_root.
24678 push_back(local_adjacency_matrix[iproc][i][j]);
24687 const unsigned root_processor = 0;
24690 OomphCommunicator* comm_pt = this->communicator_pt();
24693 unsigned n_unsigned_data_send_to_root =
24694 package_unsigned_send_data_to_root.size();
24697 Vector<int> n_unsigned_data_received_in_root(nproc, 0);
24701 MPI_Gather(&n_unsigned_data_send_to_root,
24705 &n_unsigned_data_received_in_root[0],
24713 comm_pt->mpi_comm());
24716 unsigned n_unsigned_total_data_receive_in_root = 0;
24717 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24720 n_unsigned_total_data_receive_in_root+=
24721 n_unsigned_data_received_in_root[iproc];
24725 Vector<int> root_unsigned_offsets_receive(nproc,0);
24726 root_unsigned_offsets_receive[0] = 0;
24727 for (
unsigned iproc = 1; iproc < nproc; iproc++)
24731 root_unsigned_offsets_receive[iproc] =
24732 root_unsigned_offsets_receive[iproc-1] +
24733 n_unsigned_data_received_in_root[iproc-1];
24737 if (package_unsigned_send_data_to_root.size()==0)
24739 package_unsigned_send_data_to_root.resize(1);
24744 package_unsigned_data_received_root(n_unsigned_total_data_receive_in_root);
24745 if (my_rank!=root_processor)
24748 if (package_unsigned_data_received_root.size()==0)
24750 package_unsigned_data_received_root.resize(1);
24755 MPI_Gatherv(&package_unsigned_send_data_to_root[0],
24760 n_unsigned_data_send_to_root,
24764 &package_unsigned_data_received_root[0],
24770 &n_unsigned_data_received_in_root[0],
24773 &root_unsigned_offsets_receive[0],
24780 comm_pt->mpi_comm());
24783 Vector<unsigned> package_unsigned_data_sent_from_root;
24785 Vector<int> n_unsigned_data_sent_from_root(nproc, 0);
24789 if (my_rank == root_processor)
24793 unsigned decode_counter = 0;
24801 Vector<Vector<Vector<Vector<Vector<unsigned> > > > >
24802 local_node_alias(nproc);
24804 Vector<Vector<Vector<Vector<unsigned> > > > local_adjacency_matrix(nproc);
24807 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24809 local_node_alias[iproc].resize(nproc);
24813 local_adjacency_matrix[iproc].resize(nproc);
24815 if (n_unsigned_data_received_in_root[iproc] > 0)
24819 for (
unsigned jproc = 0; jproc < nproc; jproc++)
24822 const unsigned read_jproc =
24823 package_unsigned_data_received_root[decode_counter++];
24827 if (read_jproc != jproc)
24829 std::ostringstream error_stream;
24831 <<
"The read processor is different from the jproc, this is\n"
24832 <<
"a synchronisation issue. The data are not read in the\n"
24833 <<
"sameorder as the were packaged\n"
24834 <<
"Read processor: (" << read_jproc <<
")\n"
24835 <<
"Current jproc: (" << jproc <<
")\n\n";
24836 throw OomphLibError(error_stream.str(),
24837 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
24838 OOMPH_EXCEPTION_LOCATION);
24843 const unsigned read_n_shd_nodes_iproc_jproc =
24844 package_unsigned_data_received_root[decode_counter++];
24847 local_node_alias[iproc][jproc].resize(read_n_shd_nodes_iproc_jproc);
24851 for (
unsigned ishd = 0; ishd < read_n_shd_nodes_iproc_jproc; ishd++)
24854 const unsigned read_n_alias_node_iproc_jproc =
24855 package_unsigned_data_received_root[decode_counter++];
24858 local_node_alias[iproc][jproc][ishd].
24859 resize(read_n_alias_node_iproc_jproc);
24861 for (
unsigned ialias = 0;
24862 ialias < read_n_alias_node_iproc_jproc; ialias++)
24866 local_node_alias[iproc][jproc][ishd][ialias].resize(3);
24869 local_node_alias[iproc][jproc][ishd][ialias][0] =
24870 package_unsigned_data_received_root[decode_counter++];
24873 local_node_alias[iproc][jproc][ishd][ialias][1] =
24874 package_unsigned_data_received_root[decode_counter++];
24877 local_node_alias[iproc][jproc][ishd][ialias][2] =
24878 package_unsigned_data_received_root[decode_counter++];
24885 local_adjacency_matrix[iproc][jproc].
24886 resize(read_n_shd_nodes_iproc_jproc);
24888 for (
unsigned i = 0; i < read_n_shd_nodes_iproc_jproc; i++)
24891 local_adjacency_matrix[iproc][jproc][i].
24892 resize(read_n_shd_nodes_iproc_jproc);
24893 for (
unsigned j = 0; j < read_n_shd_nodes_iproc_jproc; j++)
24896 local_adjacency_matrix[iproc][jproc][i][j] =
24897 package_unsigned_data_received_root[decode_counter++];
24909 if (decode_counter != n_unsigned_total_data_receive_in_root)
24911 std::ostringstream error_stream;
24913 <<
"The number of data decoded in root received from others\n"
24914 <<
"processors is different from the total number of data received\n"
24915 <<
"Data decoded: (" << decode_counter <<
")\n"
24916 <<
"Data received: ("<<n_unsigned_total_data_receive_in_root<<
")\n\n"
24917 <<
"This is a synchronisation issue so you are probably sending\n"
24918 <<
"more or less info. than the one that is being decoded\n\n";
24919 throw OomphLibError(error_stream.str(),
24920 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
24921 OOMPH_EXCEPTION_LOCATION);
24931 std::map<Vector<unsigned>,
bool> alias_done;
24934 Vector<Vector<Vector<unsigned> > > global_node_alias;
24937 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24939 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
24942 const unsigned n_shd_nodes_iproc_jproc =
24943 local_node_alias[iproc][jproc].size();
24946 const unsigned n_shd_nodes_jproc_iproc =
24947 local_node_alias[jproc][iproc].size();
24949 if (n_shd_nodes_iproc_jproc != n_shd_nodes_jproc_iproc)
24951 std::ostringstream error_stream;
24953 <<
"The number of nodes shared between iproc and jproc is\n"
24954 <<
"different from the number of nodes shared between jproc\n"
24956 <<
"Nodes shared between processor (" << iproc <<
") and "
24957 <<
"processor ("<<jproc<<
"): ("<<n_shd_nodes_iproc_jproc<<
")\n"
24958 <<
"Nodes shared between processor (" << jproc <<
") and "
24959 <<
"processor ("<<iproc<<
"): ("<<n_shd_nodes_jproc_iproc<<
")\n\n";
24960 throw OomphLibError(error_stream.str(),
24961 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
24962 OOMPH_EXCEPTION_LOCATION);
24967 for (
unsigned ishd = 0; ishd < n_shd_nodes_iproc_jproc; ishd++)
24971 const unsigned n_alias_iproc_jproc =
24972 local_node_alias[iproc][jproc][ishd].size();
24973 const unsigned n_alias_jproc_iproc =
24974 local_node_alias[jproc][iproc][ishd].size();
24977 Vector<Vector<unsigned> > node_alias;
24980 bool new_alias_added =
false;
24983 for (
unsigned ialias = 0; ialias < n_alias_iproc_jproc; ialias++)
24986 Vector<unsigned> current_alias =
24987 local_node_alias[iproc][jproc][ishd][ialias];
24989 if (!alias_done[current_alias])
24992 node_alias.push_back(current_alias);
24994 new_alias_added =
true;
24996 alias_done[current_alias] =
true;
25002 for (
unsigned ialias = 0; ialias < n_alias_jproc_iproc; ialias++)
25005 Vector<unsigned> current_alias =
25006 local_node_alias[jproc][iproc][ishd][ialias];
25009 if (!alias_done[current_alias])
25012 node_alias.push_back(current_alias);
25014 new_alias_added =
true;
25016 alias_done[current_alias] =
true;
25021 unsigned counter_alias = 0;
25025 unsigned n_current_alias = node_alias.size();
25026 while(new_alias_added || counter_alias < n_current_alias)
25029 new_alias_added =
false;
25031 Vector<unsigned> current_alias = node_alias[counter_alias];
25034 Vector<Vector<unsigned> > alias_of_current_alias =
25035 local_node_alias[current_alias[0]]
25037 [current_alias[2]];
25041 const unsigned n_alias = alias_of_current_alias.size();
25045 for (
unsigned k = 0; k < n_alias; k++)
25048 Vector<unsigned> add_alias =
25049 alias_of_current_alias[k];
25052 if (!alias_done[add_alias])
25055 node_alias.push_back(add_alias);
25058 new_alias_added =
true;
25060 alias_done[add_alias] =
true;
25067 Vector<Vector<unsigned> > alias_of_current_alias2 =
25068 local_node_alias[current_alias[1]]
25070 [current_alias[2]];
25074 const unsigned n_alias2 = alias_of_current_alias2.size();
25078 for (
unsigned k = 0; k < n_alias2; k++)
25081 Vector<unsigned> add_alias =
25082 alias_of_current_alias2[k];
25085 if (!alias_done[add_alias])
25088 node_alias.push_back(add_alias);
25091 new_alias_added =
true;
25093 alias_done[add_alias] =
true;
25104 n_current_alias = node_alias.size();
25110 if (node_alias.size() > 0)
25114 global_node_alias.push_back(node_alias);
25127 const unsigned n_global_shared_nodes = global_node_alias.size();
25130 Vector<Vector<Vector<int> > > local_to_global_shared_node(nproc);
25133 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25136 local_to_global_shared_node[iproc].resize(nproc);
25141 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25144 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
25147 const unsigned n_shd_nodes =
25148 local_node_alias[iproc][jproc].size();
25151 local_to_global_shared_node[iproc][jproc].resize(n_shd_nodes,-1);
25154 local_to_global_shared_node[jproc][iproc].resize(n_shd_nodes,-1);
25164 for (
unsigned k = 0 ; k < n_global_shared_nodes; k++)
25167 const unsigned n_alias_global_node = global_node_alias[k].size();
25169 for (
unsigned l = 0; l < n_alias_global_node; l++)
25172 const unsigned iproc = global_node_alias[k][l][0];
25174 const unsigned jproc = global_node_alias[k][l][1];
25176 const unsigned ishd = global_node_alias[k][l][2];
25178 local_to_global_shared_node[iproc][jproc][ishd] = k;
25185 Vector<Vector<unsigned> > global_adjacency_matrix(n_global_shared_nodes);
25187 for (
unsigned k = 0; k < n_global_shared_nodes; k++)
25190 global_adjacency_matrix[k].resize(n_global_shared_nodes,0);
25197 Vector<unsigned> global_node_degree(n_global_shared_nodes, 0);
25200 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25203 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
25206 const unsigned n_shd_nodes =
25207 local_node_alias[iproc][jproc].size();
25214 for (
unsigned ishd = 0; ishd < n_shd_nodes; ishd++)
25216 for (
unsigned jshd = ishd + 1; jshd < n_shd_nodes; jshd++)
25219 if (local_adjacency_matrix[iproc][jproc][ishd][jshd] > 0)
25224 const int global_shd_node_left =
25225 local_to_global_shared_node[iproc][jproc][ishd];
25228 const int global_shd_node_right =
25229 local_to_global_shared_node[iproc][jproc][jshd];
25234 if (global_shd_node_left == -1)
25236 std::ostringstream error_stream;
25238 <<
"The local node in processors iproc and jproc has no\n"
25239 <<
"global node assigned\n"
25240 <<
"iproc processor: (" << iproc <<
")\n"
25241 <<
"jproc processor: ("<<jproc<<
")\n"
25242 <<
"Local node: (" << ishd <<
")\n\n";
25243 throw OomphLibError(error_stream.str(),
25244 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25245 OOMPH_EXCEPTION_LOCATION);
25250 if (global_shd_node_right == -1)
25252 std::ostringstream error_stream;
25254 <<
"The local node in processors iproc and jproc has no\n"
25255 <<
"global node assigned\n"
25256 <<
"iproc processor: (" << iproc <<
")\n"
25257 <<
"jproc processor: ("<<jproc<<
")\n"
25258 <<
"Local node: (" << jshd <<
")\n\n";
25259 throw OomphLibError(error_stream.str(),
25260 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25261 OOMPH_EXCEPTION_LOCATION);
25265 const unsigned uleft =
25266 static_cast<unsigned>(global_shd_node_left);
25267 const unsigned uright =
25268 static_cast<unsigned>(global_shd_node_right);
25271 global_adjacency_matrix[uleft][uright]++;
25274 global_adjacency_matrix[uright][uleft]++;
25277 global_node_degree[uleft]++;
25280 global_node_degree[uright]++;
25294 Vector<Vector<Vector<unsigned> > > root_local_node_degree(nproc);
25296 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25298 root_local_node_degree[iproc].resize(nproc);
25302 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25305 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
25309 const unsigned n_shd_nodes = local_node_alias[iproc][jproc].size();
25312 root_local_node_degree[iproc][jproc].resize(n_shd_nodes);
25314 root_local_node_degree[jproc][iproc].resize(n_shd_nodes);
25318 for (
unsigned ishd = 0; ishd < n_shd_nodes; ishd++)
25321 const int global_shd_node_id =
25322 local_to_global_shared_node[iproc][jproc][ishd];
25326 if (global_shd_node_id == -1)
25328 std::ostringstream error_stream;
25330 <<
"The local node in processors iproc and jproc has no\n"
25331 <<
"global node assigned\n"
25332 <<
"iproc processor: (" << iproc <<
")\n"
25333 <<
"jproc processor: ("<<jproc<<
")\n"
25334 <<
"Local node: (" << ishd <<
")\n\n";
25335 throw OomphLibError(error_stream.str(),
25336 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25337 OOMPH_EXCEPTION_LOCATION);
25342 const unsigned uglobal_shd_node_id =
25343 static_cast<unsigned>(global_shd_node_id);
25346 const unsigned node_degree =
25347 global_node_degree[uglobal_shd_node_id];
25351 root_local_node_degree[iproc][jproc][ishd] = node_degree;
25353 root_local_node_degree[jproc][iproc][ishd] = node_degree;
25363 package_unsigned_data_sent_from_root.clear();
25367 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25370 unsigned count_n_data_sent_to_iproc = 0;
25371 for (
unsigned jproc = 0; jproc < nproc; jproc++)
25374 if (iproc != jproc)
25377 const unsigned n_shd_nodes =
25378 root_local_node_degree[iproc][jproc].size();
25381 count_n_data_sent_to_iproc+=n_shd_nodes;
25384 for (
unsigned ishd = 0; ishd < n_shd_nodes; ishd++)
25386 package_unsigned_data_sent_from_root.
25387 push_back(root_local_node_degree[iproc][jproc][ishd]);
25395 n_unsigned_data_sent_from_root[iproc] = count_n_data_sent_to_iproc;
25402 int n_unsigned_data_received_from_root = 0;
25405 MPI_Scatter(&n_unsigned_data_sent_from_root[0],
25411 &n_unsigned_data_received_from_root,
25418 comm_pt->mpi_comm());
25422 package_unsigned_data_received_from_root(n_unsigned_data_received_from_root);
25425 Vector<int> root_unsigned_offsets_sent(nproc,0);
25426 root_unsigned_offsets_sent[0] = 0;
25427 for (
unsigned iproc = 1; iproc < nproc; iproc++)
25430 root_unsigned_offsets_sent[iproc] =
25431 root_unsigned_offsets_sent[iproc-1] +
25432 n_unsigned_data_sent_from_root[iproc-1];
25435 if (my_rank!=root_processor)
25438 if (package_unsigned_data_sent_from_root.size()==0)
25440 package_unsigned_data_sent_from_root.resize(1);
25445 if (package_unsigned_data_received_from_root.size()==0)
25447 package_unsigned_data_received_from_root.resize(1);
25451 MPI_Scatterv(&package_unsigned_data_sent_from_root[0],
25456 &n_unsigned_data_sent_from_root[0],
25460 &root_unsigned_offsets_sent[0],
25463 &package_unsigned_data_received_from_root[0],
25471 n_unsigned_data_received_from_root,
25479 comm_pt->mpi_comm());
25484 std::map<Node*, bool> node_done;
25488 int decode_counter = 0;
25490 Vector<Vector<unsigned> > local_node_degree(nproc);
25492 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25495 if (iproc != my_rank)
25498 const unsigned n_nodes = tmp_sorted_shared_node_pt[iproc].size();
25501 package_unsigned_send_data_to_root.push_back(n_nodes);
25504 for (
unsigned ishd = 0; ishd < n_nodes; ishd++)
25508 const unsigned node_degree =
25509 package_unsigned_data_received_from_root[decode_counter++];
25512 Node* shd_node_pt =
25513 tmp_sorted_shared_node_pt[iproc][ishd];
25516 if (!node_done[shd_node_pt])
25519 global_node_degree[shd_node_pt] = node_degree;
25521 node_done[shd_node_pt] =
true;
25528 if (global_node_degree[shd_node_pt] != node_degree)
25530 std::ostringstream error_stream;
25532 <<
"The local node has already assigned a global degree,\n"
25533 <<
"however, a different degree for the same node has been\n"
25534 <<
"read from the data sent from root processor\n"
25535 <<
"iproc processor: (" << iproc <<
")\n"
25536 <<
"Local node: (" << ishd <<
")\n"
25537 <<
"---------------------------------------------------------\n"
25538 <<
"Already assigned degree: ("
25539 << global_node_degree[shd_node_pt] <<
")\n"
25540 <<
"New found degree: (" << node_degree <<
")\n"
25541 <<
"---------------------------------------------------------\n"
25542 <<
"Node coordinates: (" << shd_node_pt->x(0) <<
", "
25543 << shd_node_pt->x(1) <<
")\n\n";
25544 throw OomphLibError(error_stream.str(),
25545 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25546 OOMPH_EXCEPTION_LOCATION);
25550 #endif // #ifdef PARANOID
25560 if (decode_counter != n_unsigned_data_received_from_root)
25562 std::ostringstream error_stream;
25564 <<
"The number of data decoded received from root processor is\n"
25565 <<
"different from the total number of data received from the root\n"
25567 <<
"Data decoded: (" << decode_counter <<
")\n"
25568 <<
"Data received: ("<<n_unsigned_data_received_from_root<<
")\n\n"
25569 <<
"This is a synchronisation issue so you are probably sending\n"
25570 <<
"more or less info. than the one that is being decoded\n\n";
25571 throw OomphLibError(error_stream.str(),
25572 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25573 OOMPH_EXCEPTION_LOCATION);
25585 template <
class ELEMENT>
25588 Vector<Vector<FiniteElement*> > &unsorted_face_ele_pt,
25589 Vector<Vector<Node*> > &tmp_sorted_shared_node_pt,
25590 std::map<Node*, Vector<Vector<unsigned> > > &node_alias,
25591 Vector<Vector<Vector<unsigned> > > &adjacency_matrix)
25594 const unsigned nproc = this->communicator_pt()->nproc();
25595 const unsigned my_rank = this->communicator_pt()->my_rank();
25604 node_alias.clear();
25607 Vector<std::map<Node*, unsigned> > tmp_node_index(nproc);
25610 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25613 if (iproc != my_rank)
25616 std::map<Node*, bool> done_node;
25621 std::map<std::pair<double, double>, Node*,
classcomp> sorted_nodes_pt;
25624 const unsigned n_unsorted_face_ele =
25625 unsorted_face_ele_pt[iproc].size();
25628 for (
unsigned e = 0; e < n_unsorted_face_ele; e++)
25631 FiniteElement* face_ele_pt = unsorted_face_ele_pt[iproc][e];
25633 Node* left_node_pt = face_ele_pt->node_pt(0);
25638 if (!done_node[left_node_pt])
25640 std::pair<double, double> vertex =
25641 std::make_pair(left_node_pt->x(0), left_node_pt->x(1));
25642 sorted_nodes_pt[vertex] = left_node_pt;
25644 done_node[left_node_pt] =
true;
25648 const unsigned n_nodes = face_ele_pt->nnode();
25650 Node* right_node_pt = face_ele_pt->node_pt(n_nodes-1);
25655 if (!done_node[right_node_pt])
25657 std::pair<double, double> vertex =
25658 std::make_pair(right_node_pt->x(0), right_node_pt->x(1));
25659 sorted_nodes_pt[vertex] = right_node_pt;
25661 done_node[right_node_pt] =
true;
25670 unsigned counter = 0;
25674 for (std::map<std::pair<double, double>, Node*>::iterator it
25675 = sorted_nodes_pt.begin(); it != sorted_nodes_pt.end(); it++)
25678 Node* node_pt = (*it).second;
25680 tmp_sorted_shared_node_pt[iproc].push_back(node_pt);
25683 tmp_node_index[iproc][node_pt] = counter;
25686 Vector<unsigned> alias(3);
25688 alias[0] = my_rank;
25692 alias[2] = counter++;
25695 node_alias[node_pt].push_back(alias);
25705 for (
unsigned iproc = 0 ; iproc < nproc; iproc++)
25708 const unsigned n_shd_nodes = tmp_sorted_shared_node_pt[iproc].size();
25710 adjacency_matrix[iproc].resize(n_shd_nodes);
25711 for (
unsigned i = 0; i < n_shd_nodes; i++)
25714 adjacency_matrix[iproc][i].resize(n_shd_nodes);
25717 for (
unsigned j = 0; j < n_shd_nodes; j++)
25719 adjacency_matrix[iproc][i][j] = 0;
25727 for (
unsigned iproc = 0 ; iproc < nproc; iproc++)
25730 if (iproc != my_rank)
25733 const unsigned n_unsorted_face_ele =
25734 unsorted_face_ele_pt[iproc].size();
25737 for (
unsigned e = 0; e < n_unsorted_face_ele; e++)
25740 FiniteElement* face_ele_pt = unsorted_face_ele_pt[iproc][e];
25742 Node* left_node_pt = face_ele_pt->node_pt(0);
25745 const unsigned n_nodes = face_ele_pt->nnode();
25747 Node* right_node_pt = face_ele_pt->node_pt(n_nodes-1);
25750 const unsigned left_node_index = tmp_node_index[iproc][left_node_pt];
25751 const unsigned right_node_index = tmp_node_index[iproc][right_node_pt];
25755 adjacency_matrix[iproc][left_node_index][right_node_index]++;
25757 adjacency_matrix[iproc][right_node_index][left_node_index]++;
25771 template <
class ELEMENT>
25774 const unsigned &shd_bnd_id, Vector<Vector<Node*> > &tmp_segment_nodes)
25777 tmp_segment_nodes.clear();
25784 Vector<FiniteElement*> halo_shared_face_ele_pt;
25787 Vector<FiniteElement*> nonhalo_shared_face_ele_pt;
25791 const unsigned nshared_bound_ele =
25792 this->nshared_boundary_element(shd_bnd_id);
25796 for (
unsigned e = 0; e < nshared_bound_ele; e++)
25799 FiniteElement* bulk_ele_pt =
25800 this->shared_boundary_element_pt(shd_bnd_id, e);
25803 int face_index = this->face_index_at_shared_boundary(shd_bnd_id, e);
25807 FiniteElement* face_ele_pt =
25808 new DummyFaceElement<ELEMENT>(bulk_ele_pt, face_index);
25811 if (!bulk_ele_pt->is_halo())
25814 nonhalo_shared_face_ele_pt.push_back(face_ele_pt);
25820 halo_shared_face_ele_pt.push_back(face_ele_pt);
25827 std::map<FiniteElement*, bool> shared_face_done;
25830 const unsigned nnonhalo_face_shared_ele =
25831 nonhalo_shared_face_ele_pt.size();
25837 const unsigned nhalo_face_shared_ele =
25838 halo_shared_face_ele_pt.size();
25842 if (nshared_bound_ele / 2 != nnonhalo_face_shared_ele)
25844 std::ostringstream error_message;
25846 <<
"The number of shared boundary elements (" << nshared_bound_ele
25847 <<
") is not the double\nof the number of unsorted nonhalo shared "
25848 <<
"face boundary elements (" << nnonhalo_face_shared_ele
25849 <<
")\n for the current boundary ("<< shd_bnd_id <<
")\n\n";
25850 throw OomphLibError(error_message.str(),
25851 "RefineableTriangleMesh::get_shared_boundary_segment_nodes_helper()",
25852 OOMPH_EXCEPTION_LOCATION);
25857 if (nshared_bound_ele / 2 != nhalo_face_shared_ele)
25859 std::ostringstream error_message;
25861 <<
"The number of shared boundary elements (" << nshared_bound_ele
25862 <<
") is not the double\nof the number of unsorted halo shared "
25863 <<
"face boundary elements (" << nhalo_face_shared_ele
25864 <<
")\n for the current boundary ("<< shd_bnd_id <<
")\n\n";
25865 throw OomphLibError(error_message.str(),
25866 "RefineableTriangleMesh::get_shared_boundary_segment_nodes_helper()",
25867 OOMPH_EXCEPTION_LOCATION);
25873 for (
unsigned inh = 0; inh < nnonhalo_face_shared_ele; inh++)
25876 FiniteElement* nonhalo_face_ele_pt = nonhalo_shared_face_ele_pt[inh];
25879 const unsigned nnodes_nh = nonhalo_face_ele_pt->nnode();
25881 Node* nh_first_node_pt = nonhalo_face_ele_pt->node_pt(0);
25882 Node* nh_last_node_pt = nonhalo_face_ele_pt->node_pt(nnodes_nh-1);
25886 for (
unsigned ih = 0; ih < nhalo_face_shared_ele; ih++)
25889 FiniteElement* halo_face_ele_pt = halo_shared_face_ele_pt[ih];
25892 if (!shared_face_done[halo_face_ele_pt])
25895 const unsigned nnodes_h = halo_face_ele_pt->nnode();
25897 Node* h_first_node_pt = halo_face_ele_pt->node_pt(0);
25898 Node* h_last_node_pt = halo_face_ele_pt->node_pt(nnodes_h-1);
25902 if (nh_first_node_pt == h_first_node_pt &&
25903 nh_last_node_pt == h_last_node_pt)
25906 shared_face_done[nonhalo_face_ele_pt] =
true;
25907 shared_face_done[halo_face_ele_pt] =
true;
25913 else if (nh_first_node_pt == h_last_node_pt &&
25914 nh_last_node_pt == h_first_node_pt)
25917 shared_face_done[nonhalo_face_ele_pt] =
true;
25918 shared_face_done[halo_face_ele_pt] =
true;
25933 if ((nnonhalo_face_shared_ele + nhalo_face_shared_ele) !=
25934 shared_face_done.size())
25936 std::ostringstream error_message;
25938 <<
"The number of DONE shared boundary face elements ("
25939 << shared_face_done.size() <<
") is not the same\n as the sum of"
25940 <<
"the nonhalo face shared boundary elements ("
25941 << nnonhalo_face_shared_ele <<
")\nand the halo face shared "
25942 <<
"boundary elements ("<< nhalo_face_shared_ele <<
") for the\n/"
25943 <<
"current boundary (" << shd_bnd_id <<
")\n\n";
25944 throw OomphLibError(error_message.str(),
25945 "RefineableTriangleMesh::get_shared_boundary_segment_nodes_helper()",
25946 OOMPH_EXCEPTION_LOCATION);
25948 #endif // #ifdef PARANOID
25958 shared_face_done.clear();
25960 unsigned nsorted_face_ele = 0;
25963 std::list<Node*> sorted_nodes;
25966 FiniteElement* root_face_ele_pt = nonhalo_shared_face_ele_pt[0];
25967 nsorted_face_ele++;
25970 shared_face_done[root_face_ele_pt] =
true;
25973 const unsigned nnodes_root = root_face_ele_pt->nnode();
25974 Node *first_node_pt = root_face_ele_pt->node_pt(0);
25975 Node *last_node_pt = root_face_ele_pt->node_pt(nnodes_root-1);
25978 sorted_nodes.push_back(first_node_pt);
25979 sorted_nodes.push_back(last_node_pt);
25982 while (nsorted_face_ele < nnonhalo_face_shared_ele)
25985 bool node_added =
false;
25989 for (
unsigned iface = 1; iface < nnonhalo_face_shared_ele; iface++)
25991 FiniteElement* tmp_shared_face_ele_pt =
25992 nonhalo_shared_face_ele_pt[iface];
25995 if (!shared_face_done[tmp_shared_face_ele_pt])
25998 const unsigned tmp_nnodes = tmp_shared_face_ele_pt->nnode();
26001 Node* left_node_pt = tmp_shared_face_ele_pt->node_pt(0);
26002 Node* right_node_pt = tmp_shared_face_ele_pt->node_pt(tmp_nnodes-1);
26004 if (left_node_pt == first_node_pt)
26007 sorted_nodes.push_front(right_node_pt);
26008 first_node_pt = right_node_pt;
26011 else if (left_node_pt == last_node_pt)
26014 sorted_nodes.push_back(right_node_pt);
26015 last_node_pt = right_node_pt;
26018 else if (right_node_pt == first_node_pt)
26021 sorted_nodes.push_front(left_node_pt);
26022 first_node_pt = left_node_pt;
26025 else if (right_node_pt == last_node_pt)
26028 sorted_nodes.push_back(left_node_pt);
26029 last_node_pt = left_node_pt;
26037 shared_face_done[tmp_shared_face_ele_pt] =
true;
26038 nsorted_face_ele++;
26054 for (
unsigned inh = 0; inh < nnonhalo_face_shared_ele; inh++)
26056 delete nonhalo_shared_face_ele_pt[inh];
26057 nonhalo_shared_face_ele_pt[inh] = 0;
26062 for (
unsigned ih = 0; ih < nhalo_face_shared_ele; ih++)
26064 delete halo_shared_face_ele_pt[ih];
26065 halo_shared_face_ele_pt[ih] = 0;
26073 const unsigned n_nodes = sorted_nodes.size();
26076 tmp_segment_nodes.resize(1);
26077 tmp_segment_nodes[0].resize(n_nodes);
26080 unsigned counter = 0;
26083 for (std::list<Node*>::iterator it = sorted_nodes.begin();
26084 it != sorted_nodes.end(); it++)
26086 tmp_segment_nodes[0][counter] = (*it);
26098 template<
class ELEMENT>
26102 Vector<Vector<FiniteElement*> > &f_haloed_ele_pt,
26103 FiniteElement* ele_pt)
26106 const unsigned nbound = this->initial_shared_boundary_id();
26109 const unsigned nproc = this->communicator_pt()->nproc();
26114 Vector<unsigned> associated_boundaries;
26115 Vector<unsigned> face_index_on_boundary;
26117 unsigned counter_face_indexes = 0;
26119 for (
unsigned b = 0; b < nbound; b++)
26122 const unsigned nboundary_ele = nboundary_element(b);
26123 for (
unsigned e = 0; e < nboundary_ele; e++)
26125 if (ele_pt == this->boundary_element_pt(b,e))
26128 associated_boundaries.push_back(b);
26130 face_index_on_boundary.push_back(face_index_at_boundary(b,e));
26131 counter_face_indexes++;
26133 if (counter_face_indexes > 2)
26135 std::stringstream error_message;
26137 <<
"A triangular element can not have more than two of its faces "
26138 <<
"on a boundary!!!\n\n";
26139 throw OomphLibError(error_message.str(),
26140 "RefineableTriangleMesh::get_required_elemental_information_helper()",
26141 OOMPH_EXCEPTION_LOCATION);
26145 if (counter_face_indexes==2) {
break;}
26146 #endif // #ifdef PARANOID
26156 const unsigned nassociated_boundaries = associated_boundaries.size();
26157 if (nassociated_boundaries > 0)
26159 Flat_packed_unsigneds.push_back(1);
26160 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26161 Flat_packed_unsigneds_string.push_back(
"The element is a boundary element");
26163 Flat_packed_unsigneds.push_back(nassociated_boundaries);
26164 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26165 std::stringstream junk;
26166 junk <<
"The elements is associated to " << nassociated_boundaries <<
" boundaries";
26167 Flat_packed_unsigneds_string.push_back(junk.str());
26174 for (
unsigned i = 0; i < nassociated_boundaries; i++)
26176 unsigned b = associated_boundaries[i];
26177 Flat_packed_unsigneds.push_back(b);
26178 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26179 std::stringstream junk;
26180 junk <<
"Element associated to boundary " << b <<
" of " << nassociated_boundaries <<
" total associated boundaries";
26181 Flat_packed_unsigneds_string.push_back(junk.str());
26183 unsigned f = face_index_on_boundary[i];
26184 Flat_packed_unsigneds.push_back(f);
26185 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26186 std::stringstream junk2;
26187 junk2 <<
"Face index " << f <<
" for associated boundary " << b;
26188 Flat_packed_unsigneds_string.push_back(junk2.str());
26198 Vector<Vector<unsigned> > associated_boundaries_and_regions;
26199 Vector<unsigned> face_index_on_boundary_and_region;
26202 const unsigned n_regions = this->nregion();
26207 unsigned counter_face_indexes_in_regions = 0;
26209 for (
unsigned b = 0; b < nbound; b++)
26212 for (
unsigned i_reg = 0 ; i_reg < n_regions; i_reg++)
26215 const unsigned region_id =
26216 static_cast<unsigned>(this->Region_attribute[i_reg]);
26221 const unsigned nele_in_region =
26222 this->nboundary_element_in_region(b, region_id);
26223 for (
unsigned ee = 0; ee < nele_in_region; ee++)
26228 this->boundary_element_in_region_pt(b, region_id, ee))
26232 Vector<unsigned> bound_and_region(2);
26235 bound_and_region[0] = b;
26237 bound_and_region[1] = region_id;
26240 associated_boundaries_and_regions.push_back(bound_and_region);
26242 face_index_on_boundary_and_region.push_back(
26243 this->face_index_at_boundary_in_region(b,region_id,ee));
26247 counter_face_indexes_in_regions++;
26250 if (counter_face_indexes_in_regions > 2)
26252 std::stringstream error_message;
26254 <<
"A triangular element can not have more than two of its\n"
26255 <<
"faces on a boundary!!!\n\n";
26256 throw OomphLibError(error_message.str(),
26257 "RefineableTriangleMesh::get_required_elemental_information_helper()",
26258 OOMPH_EXCEPTION_LOCATION);
26273 const unsigned nassociated_boundaries_and_regions =
26274 associated_boundaries_and_regions.size();
26275 if (nassociated_boundaries_and_regions > 0)
26277 Flat_packed_unsigneds.push_back(1);
26278 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26279 Flat_packed_unsigneds_string.push_back(
"The element is associated to boundaries and regions");
26282 Flat_packed_unsigneds.push_back(nassociated_boundaries_and_regions);
26283 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26284 std::stringstream junk;
26285 junk <<
"The element is associated to " << nassociated_boundaries_and_regions <<
" boundaries-regions";
26286 Flat_packed_unsigneds_string.push_back(junk.str());
26293 for (
unsigned i = 0; i < nassociated_boundaries_and_regions; i++)
26295 const unsigned b = associated_boundaries_and_regions[i][0];
26296 Flat_packed_unsigneds.push_back(b);
26297 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26298 std::stringstream junk;
26299 junk <<
"Element associated to boundary " << b <<
" of " << nassociated_boundaries_and_regions <<
" total associated boundaries-regions";
26300 Flat_packed_unsigneds_string.push_back(junk.str());
26303 const unsigned r = associated_boundaries_and_regions[i][1];
26304 Flat_packed_unsigneds.push_back(r);
26305 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26306 std::stringstream junk2;
26307 junk2 <<
"Element associated to region " << r <<
" of " << nassociated_boundaries_and_regions <<
" total associated boundaries-regions";
26308 Flat_packed_unsigneds_string.push_back(junk2.str());
26311 const unsigned f = face_index_on_boundary_and_region[i];
26312 Flat_packed_unsigneds.push_back(f);
26313 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26314 std::stringstream junk3;
26315 junk3 <<
"Face index " << f <<
" for associated boundary-region (" << b <<
"-" << r <<
")";
26316 Flat_packed_unsigneds_string.push_back(junk3.str());
26322 Flat_packed_unsigneds.push_back(0);
26323 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26324 Flat_packed_unsigneds_string.push_back(
"The element is NOT associated to boundaries and regions");
26331 Flat_packed_unsigneds.push_back(0);
26332 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26333 Flat_packed_unsigneds_string.push_back(
"The element is not associated to any original boundary");
26342 Vector<unsigned> associated_shared_boundaries;
26343 Vector<unsigned> face_index_on_shared_boundary;
26346 Vector<unsigned> my_rank_shared_boundaries_ids;
26347 this->shared_boundaries_in_this_processor(my_rank_shared_boundaries_ids);
26350 const unsigned nmy_rank_shd_bnd = my_rank_shared_boundaries_ids.size();
26352 for (
unsigned i = 0; i < nmy_rank_shd_bnd; i++)
26355 const unsigned sb = my_rank_shared_boundaries_ids[i];
26358 const unsigned nboundary_ele = this->nshared_boundary_element(sb);
26359 for (
unsigned e = 0; e < nboundary_ele; e++)
26361 if (ele_pt == this->shared_boundary_element_pt(sb,e))
26364 associated_shared_boundaries.push_back(sb);
26366 face_index_on_shared_boundary.push_back(
26367 this->face_index_at_shared_boundary(sb, e));
26374 const unsigned nassociated_shared_boundaries =
26375 associated_shared_boundaries.size();
26376 if (nassociated_shared_boundaries > 0)
26378 Flat_packed_unsigneds.push_back(3);
26379 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26380 Flat_packed_unsigneds_string.push_back(
"The element is a shared boundary element");
26382 Flat_packed_unsigneds.push_back(nassociated_shared_boundaries);
26383 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26384 std::stringstream junk;
26385 junk <<
"The elements is associated to " << nassociated_shared_boundaries <<
"shared boundaries";
26386 Flat_packed_unsigneds_string.push_back(junk.str());
26390 for (
unsigned i = 0; i < nassociated_shared_boundaries; i++)
26392 const unsigned b = associated_shared_boundaries[i];
26393 Flat_packed_unsigneds.push_back(b);
26394 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26395 std::stringstream junk;
26396 junk <<
"Element associated to shared boundary " << b <<
" of " << nassociated_shared_boundaries <<
" total associated boundaries";
26397 Flat_packed_unsigneds_string.push_back(junk.str());
26400 const unsigned f = face_index_on_shared_boundary[i];
26401 Flat_packed_unsigneds.push_back(f);
26402 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26403 std::stringstream junk2;
26404 junk2 <<
"Face index " << f <<
" for associated shared boundary " << b;
26405 Flat_packed_unsigneds_string.push_back(junk2.str());
26411 Flat_packed_unsigneds.push_back(0);
26412 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26413 Flat_packed_unsigneds_string.push_back(
"The element is not associated to any shared boundary");
26420 Vector<Vector<unsigned> > index_haloed(nproc);
26423 for (
unsigned jproc = 0; jproc < nproc; jproc++)
26426 const unsigned n_haloed_jproc = f_haloed_ele_pt[jproc].size();
26428 for (
unsigned ihd =0; ihd < n_haloed_jproc; ihd++)
26431 if (ele_pt == f_haloed_ele_pt[jproc][ihd])
26434 index_haloed[jproc].push_back(ihd);
26445 for (
unsigned jproc = 0; jproc < nproc; jproc++)
26448 const unsigned n_index_haloed_jproc = index_haloed[jproc].size();
26449 Flat_packed_unsigneds.push_back(n_index_haloed_jproc);
26450 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26451 Flat_packed_unsigneds_string.push_back(
"The number of haloed indexes the element is with processor jproc");
26453 for (
unsigned ihd = 0; ihd < n_index_haloed_jproc; ihd++)
26455 Flat_packed_unsigneds.push_back(index_haloed[jproc][ihd]);
26456 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26457 Flat_packed_unsigneds_string.push_back(
"The haloed index of the element with jproc");
26469 template <
class ELEMENT>
26472 Vector<Vector<FiniteElement*> >&f_halo_ele_pt,
26473 Vector<Node*> &new_nodes_on_domain,
26477 const unsigned nnew_nodes_on_domain= new_nodes_on_domain.size();
26478 const unsigned new_added_node_index =
26479 this->try_to_add_node_pt_load_balance(new_nodes_on_domain, nod_pt);
26482 if (new_added_node_index == nnew_nodes_on_domain)
26484 Flat_packed_unsigneds.push_back(1);
26486 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26487 std::stringstream junk;
26488 junk <<
"Node needs to be constructed [size="
26489 << Flat_packed_unsigneds.size() <<
"]; last entry: "
26490 << Flat_packed_unsigneds[Flat_packed_unsigneds.size()-1];
26491 Flat_packed_unsigneds_string.push_back(junk.str());
26497 get_required_nodal_information_load_balance_helper(f_halo_ele_pt,
26503 Flat_packed_unsigneds.push_back(0);
26504 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26505 std::stringstream junk;
26506 junk <<
"Node was already added [size="
26507 << Flat_packed_unsigneds.size() <<
"]; last entry: "
26508 << Flat_packed_unsigneds[Flat_packed_unsigneds.size()-1];
26510 Flat_packed_unsigneds_string.push_back(junk.str());
26515 Flat_packed_unsigneds.push_back(new_added_node_index);
26516 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26517 Flat_packed_unsigneds_string.push_back(
"new added node index");
26528 template<
class ELEMENT>
26531 Vector<Vector<FiniteElement*> > &f_halo_ele_pt,
26535 unsigned my_rank = this->communicator_pt()->my_rank();
26536 const unsigned nproc = this->communicator_pt()->nproc();
26541 unsigned n_val=nod_pt->nvalue();
26542 Flat_packed_unsigneds.push_back(n_val);
26543 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26544 Flat_packed_unsigneds_string.push_back(
"Number of values");
26547 unsigned n_dim=nod_pt->ndim();
26551 if (this->Time_stepper_pt!=0)
26554 n_prev=this->Time_stepper_pt->ntstorage();
26560 Vector<unsigned> original_boundaries;
26563 const unsigned n_bnd = this->initial_shared_boundary_id();
26564 for (
unsigned bb=0;bb<n_bnd;bb++)
26567 if (nod_pt->is_on_boundary(bb))
26569 original_boundaries.push_back(bb);
26574 const unsigned n_original_boundaries = original_boundaries.size();
26576 if (n_original_boundaries > 0)
26579 Flat_packed_unsigneds.push_back(2);
26580 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26581 Flat_packed_unsigneds_string.push_back(
"Node is on the original boundaries");
26584 Flat_packed_unsigneds.push_back(n_original_boundaries);
26585 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26586 std::stringstream junk;
26587 junk <<
"Node is on "<< n_original_boundaries <<
" original boundaries";
26588 Flat_packed_unsigneds_string.push_back(junk.str());
26592 for (
unsigned i=0;i<n_original_boundaries;i++)
26594 Flat_packed_unsigneds.push_back(original_boundaries[i]);
26595 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26596 std::stringstream junk;
26597 junk<<
"Node is on boundary "<<original_boundaries[i]<<
" of "<< nb;
26598 Flat_packed_unsigneds_string.push_back(junk.str());
26601 Vector<double> zeta(1);
26602 nod_pt->get_coordinates_on_boundary(original_boundaries[i],zeta);
26603 Flat_packed_doubles.push_back(zeta[0]);
26609 Flat_packed_unsigneds.push_back(0);
26610 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26611 Flat_packed_unsigneds_string.push_back(
"Node is on any original boundary");
26617 bool node_on_shared_boundary =
false;
26620 const unsigned n_shd_bnd = this->nshared_boundaries(my_rank, iproc);
26621 for (
unsigned bb=0;bb<n_shd_bnd;bb++)
26624 unsigned i_bnd = this->shared_boundaries_ids(my_rank, iproc, bb);
26626 if (this->is_node_on_shared_boundary(i_bnd, nod_pt))
26628 node_on_shared_boundary =
true;
26636 if (node_on_shared_boundary)
26638 Flat_packed_unsigneds.push_back(1);
26639 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26640 Flat_packed_unsigneds_string.push_back(
"Node is on shared boundary");
26644 Vector<unsigned> shd_boundaries;
26646 for (
unsigned bb = 0; bb < n_shd_bnd; bb++)
26649 const unsigned i_bnd =
26650 this->shared_boundaries_ids(my_rank, iproc, bb);
26652 if (this->is_node_on_shared_boundary(i_bnd, nod_pt))
26654 shd_boundaries.push_back(i_bnd);
26659 const unsigned n_shd_bnd_is_on = shd_boundaries.size();
26661 Flat_packed_unsigneds.push_back(n_shd_bnd_is_on);
26662 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26663 std::stringstream junk;
26664 junk <<
"Node is on "<< n_shd_bnd_is_on <<
" shared boundaries";
26665 Flat_packed_unsigneds_string.push_back(junk.str());
26669 for (
unsigned i=0;i<n_shd_bnd_is_on;i++)
26671 Flat_packed_unsigneds.push_back(shd_boundaries[i]);
26672 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26673 std::stringstream junk;
26674 junk <<
"Node is on boundary " << shd_boundaries[i] <<
" of " << nb;
26675 Flat_packed_unsigneds_string.push_back(junk.str());
26681 unsigned shared_boundary_id = shd_boundaries[0];
26683 const unsigned n_nodes_on_shared_boundary =
26684 nsorted_shared_boundary_node(shared_boundary_id);
26686 unsigned index_node_on_shared_boundary;
26689 bool found_index_node_on_shared_boundary =
false;
26692 for (
unsigned i = 0; i < n_nodes_on_shared_boundary; i++)
26695 Node* shared_node_pt =
26696 sorted_shared_boundary_node_pt(shared_boundary_id, i);
26698 if (shared_node_pt == nod_pt)
26701 index_node_on_shared_boundary = i;
26704 found_index_node_on_shared_boundary =
true;
26712 if (!found_index_node_on_shared_boundary)
26714 std::ostringstream error_message;
26716 <<
"The index of the node on boundary ("
26717 <<shared_boundary_id<<
") was not found.\n"
26718 <<
"The node coordinates are ("<<nod_pt->x(0)<<
","
26719 <<nod_pt->x(1)<<
").\n";
26720 throw OomphLibError(
26721 error_message.str(),
26722 "RefineableTriangleMesh::get_required_nodal_information_helper()",
26723 OOMPH_EXCEPTION_LOCATION);
26727 Flat_packed_unsigneds.push_back(index_node_on_shared_boundary);
26728 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26729 std::stringstream junk2;
26730 junk2 <<
"Node index on boundary "<<
boundaries[0]<<
" is "
26731 <<index_node_on_shared_boundary;
26732 Flat_packed_unsigneds_string.push_back(junk2.str());
26739 Flat_packed_unsigneds.push_back(0);
26740 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26741 Flat_packed_unsigneds_string.push_back(
"Node is not on a shared boundary");
26756 bool node_on_shared_boundary_with_other_processors =
false;
26758 unsigned nshared_boundaries_with_other_processors_have_node = 0;
26762 for (
unsigned jproc = 0; jproc < nproc; jproc++)
26766 if (jproc != iproc)
26769 const unsigned n_jshd_bnd =
26770 this->nshared_boundaries(my_rank, jproc);
26772 for (
unsigned bb=0;bb<n_jshd_bnd;bb++)
26775 const unsigned j_shd_bnd =
26776 this->shared_boundaries_ids(my_rank, jproc, bb);
26778 if (this->is_node_on_shared_boundary(j_shd_bnd, nod_pt))
26786 node_on_shared_boundary_with_other_processors =
true;
26789 nshared_boundaries_with_other_processors_have_node++;
26800 if (node_on_shared_boundary_with_other_processors)
26802 Flat_packed_unsigneds.push_back(4);
26803 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26804 Flat_packed_unsigneds_string.push_back(
"Node is on shared boundary no related with the received processor: 4");
26810 Flat_packed_unsigneds.push_back(nshared_boundaries_with_other_processors_have_node);
26811 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26812 std::stringstream junk;
26813 junk <<
"Number of other shared boundaries that the node is on: "
26814 << nshared_boundaries_with_other_processors_have_node;
26815 Flat_packed_unsigneds_string.push_back(junk.str());
26819 unsigned counter_shd_bnd_with_other_procs_have_node = 0;
26824 Vector<unsigned> other_processor_1;
26825 Vector<unsigned> other_processor_2;
26826 Vector<unsigned> shd_bnd_ids;
26827 Vector<unsigned> indexes;
26829 for (
unsigned jproc = 0; jproc < nproc; jproc++)
26833 if (jproc != iproc)
26837 const unsigned n_jshd_bnd =
26838 this->nshared_boundaries(my_rank, jproc);
26839 for (
unsigned bb = 0; bb < n_jshd_bnd; bb++)
26842 const unsigned j_shd_bnd =
26843 this->shared_boundaries_ids(my_rank, jproc, bb);
26845 if (this->is_node_on_shared_boundary(j_shd_bnd, nod_pt))
26848 other_processor_1.push_back(my_rank);
26850 other_processor_2.push_back(jproc);
26852 shd_bnd_ids.push_back(j_shd_bnd);
26855 counter_shd_bnd_with_other_procs_have_node++;
26866 const unsigned n_other_processors = other_processor_1.size();
26868 for (
unsigned i = 0; i < n_other_processors; i++)
26871 unsigned shd_bnd_id = shd_bnd_ids[i];
26873 const unsigned n_nodes_on_shd_bnd =
26874 nsorted_shared_boundary_node(shd_bnd_id);
26877 bool found_index_node_on_shared_boundary =
false;
26879 for (
unsigned i = 0; i < n_nodes_on_shd_bnd; i++)
26882 Node* shared_node_pt =
26883 sorted_shared_boundary_node_pt(shd_bnd_id, i);
26885 if (shared_node_pt == nod_pt)
26891 indexes.push_back(i);
26894 found_index_node_on_shared_boundary =
true;
26902 if (!found_index_node_on_shared_boundary)
26904 std::ostringstream error_message;
26906 <<
"The index of the node on boundary ("
26907 <<shd_bnd_id<<
"), shared by other processors\nwas not found.\n"
26908 <<
"The node coordinates are ("<<nod_pt->x(0)<<
","
26909 <<nod_pt->x(1)<<
").\n";
26910 throw OomphLibError(
26911 error_message.str(),
26912 "RefineableTriangleMesh::get_required_nodal_information_helper()",
26913 OOMPH_EXCEPTION_LOCATION);
26922 if (counter_shd_bnd_with_other_procs_have_node !=
26923 nshared_boundaries_with_other_processors_have_node)
26925 std::ostringstream error_message;
26927 <<
"The number of shared boundaries where the node is on "
26928 <<
"is different:\n"
26929 <<
"nshared_boundaries_with_other_processors_have_node: ("
26930 << nshared_boundaries_with_other_processors_have_node
26932 <<
"counter_shd_bnd_with_other_procs_have_node: ("
26933 << counter_shd_bnd_with_other_procs_have_node
26935 throw OomphLibError(
26936 error_message.str(),
26937 "RefineableTriangleMesh::get_required_nodal_information_helper()",
26938 OOMPH_EXCEPTION_LOCATION);
26944 for (
unsigned i = 0; i < n_other_processors; i++)
26946 Flat_packed_unsigneds.push_back(other_processor_1[i]);
26947 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26948 std::stringstream junk1;
26949 junk1 <<
"Processor where the other shared boundary "
26950 <<
"has the node: " << other_processor_1[i];
26951 Flat_packed_unsigneds_string.push_back(junk1.str());
26954 Flat_packed_unsigneds.push_back(other_processor_2[i]);
26955 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26956 std::stringstream junk2;
26957 junk2 <<
"Processor where the other shared boundary "
26958 <<
"has the node: " << other_processor_2[i];
26959 Flat_packed_unsigneds_string.push_back(junk2.str());
26962 Flat_packed_unsigneds.push_back(shd_bnd_ids[i]);
26963 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26964 std::stringstream junk3;
26965 junk3 <<
"Other shared boundary id where the node is on"
26967 Flat_packed_unsigneds_string.push_back(junk3.str());
26970 Flat_packed_unsigneds.push_back(indexes[i]);
26971 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26972 std::stringstream junk4;
26973 junk4 <<
"Node index on other shared boundary "
26976 Flat_packed_unsigneds_string.push_back(junk4.str());
26984 Flat_packed_unsigneds.push_back(0);
26985 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26986 Flat_packed_unsigneds_string.push_back(
"Node is on any shared boundary with other processors");
27013 Vector<Vector<unsigned> > halo_element_number(nproc);
27015 Vector<Vector<unsigned> > halo_node_number_in_halo_element(nproc);
27018 for (
unsigned jproc = 0; jproc < nproc; jproc++)
27021 const unsigned n_halo_jproc = f_halo_ele_pt[jproc].size();
27023 for (
unsigned jh = 0; jh < n_halo_jproc; jh++)
27025 FiniteElement* halo_ele_pt = f_halo_ele_pt[jproc][jh];
27027 const unsigned n_node = halo_ele_pt->nnode();
27029 for (
unsigned n = 0; n < n_node; n++)
27032 if (nod_pt == halo_ele_pt->node_pt(n))
27034 halo_element_number[jproc].push_back(jh);
27035 halo_node_number_in_halo_element[jproc].push_back(n);
27051 for (
unsigned jproc = 0; jproc < nproc; jproc++)
27055 const unsigned n_jproc_halo_ele_node_is_on =
27056 halo_element_number[jproc].size();
27058 Flat_packed_unsigneds.push_back(n_jproc_halo_ele_node_is_on);
27059 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27060 std::stringstream junk5;
27061 junk5 <<
"Node is on " << n_jproc_halo_ele_node_is_on <<
" halo "
27062 <<
"elements with " << jproc <<
"-th processor";
27063 Flat_packed_unsigneds_string.push_back(junk5.str());
27068 for (
unsigned i = 0; i < n_jproc_halo_ele_node_is_on; i++)
27071 const unsigned halo_element_index = halo_element_number[jproc][i];
27072 Flat_packed_unsigneds.push_back(halo_element_index);
27073 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27074 std::stringstream junk6;
27075 junk6 <<
"Halo element index is ("<<halo_element_index
27076 <<
") with processor ("<<jproc<<
")";
27077 Flat_packed_unsigneds_string.push_back(junk6.str());
27080 const unsigned node_index = halo_node_number_in_halo_element[jproc][i];
27081 Flat_packed_unsigneds.push_back(node_index);
27082 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27083 std::stringstream junk7;
27084 junk7 <<
"The node index on the halo element index is ("
27086 Flat_packed_unsigneds_string.push_back(junk7.str());
27101 bool on_halo_element_with_iproc_processor =
false;
27102 if (halo_element_number[iproc].size() > 0)
27104 on_halo_element_with_iproc_processor =
true;
27108 if (!node_on_shared_boundary && !on_halo_element_with_iproc_processor)
27115 AlgebraicNode* alg_nod_pt=
dynamic_cast<AlgebraicNode*
>(nod_pt);
27122 unsigned update_id=alg_nod_pt->node_update_fct_id();
27123 Flat_packed_unsigneds.push_back(update_id);
27124 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27125 Flat_packed_unsigneds_string.push_back(
"Alg Node update id");
27129 unsigned n_ref_val=alg_nod_pt->nref_value();
27130 Flat_packed_unsigneds.push_back(n_ref_val);
27131 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27132 Flat_packed_unsigneds_string.push_back(
"Alg Node n ref values");
27134 for (
unsigned i_ref_val=0;i_ref_val<n_ref_val;i_ref_val++)
27136 Flat_packed_doubles.push_back(alg_nod_pt->ref_value(i_ref_val));
27140 unsigned n_geom_obj=alg_nod_pt->ngeom_object();
27141 Flat_packed_unsigneds.push_back(n_geom_obj);
27142 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27143 Flat_packed_unsigneds_string.push_back(
"Alg Node n geom objects");
27145 for (
unsigned i_geom=0;i_geom<n_geom_obj;i_geom++)
27147 GeomObject* geom_obj_pt=alg_nod_pt->geom_object_pt(i_geom);
27150 unsigned n_geom_list=alg_mesh_pt->ngeom_object_list_pt();
27153 unsigned found_geom_object=0;
27154 for (
unsigned i_list=0;i_list<n_geom_list;i_list++)
27156 if (geom_obj_pt==alg_mesh_pt->geom_object_list_pt(i_list))
27158 found_geom_object=i_list;
27161 Flat_packed_unsigneds.push_back(found_geom_object);
27162 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27163 Flat_packed_unsigneds_string.push_back(
"Found geom object");
27169 SolidNode* solid_nod_pt=
dynamic_cast<SolidNode*
>(nod_pt);
27170 if (solid_nod_pt!=0)
27172 unsigned n_solid_val=solid_nod_pt->variable_position_pt()->nvalue();
27173 for (
unsigned i_val=0;i_val<n_solid_val;i_val++)
27175 for (
unsigned t=0;
t<n_prev;
t++)
27177 Flat_packed_doubles.push_back(solid_nod_pt->variable_position_pt()->
27182 Vector<double> values_solid_node;
27183 solid_nod_pt->add_values_to_vector(values_solid_node);
27184 const unsigned nvalues_solid_node = values_solid_node.size();
27185 Flat_packed_unsigneds.push_back(nvalues_solid_node);
27186 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27187 std::stringstream junk;
27188 junk <<
"Number of values solid node: "
27189 << nvalues_solid_node;
27190 Flat_packed_unsigneds_string.push_back(junk.str());
27192 for (
unsigned i = 0; i < nvalues_solid_node; i++)
27194 Flat_packed_doubles.push_back(values_solid_node[i]);
27199 for (
unsigned i_val=0;i_val<n_val;i_val++)
27201 for (
unsigned t=0;
t<n_prev;
t++)
27203 Flat_packed_doubles.push_back(nod_pt->value(
t,i_val));
27208 for (
unsigned idim=0;idim<n_dim;idim++)
27210 for (
unsigned t=0;
t<n_prev;
t++)
27212 Flat_packed_doubles.push_back(nod_pt->x(
t,idim));
27226 template <
class ELEMENT>
27229 Vector<Vector<FiniteElement*> > &f_haloed_ele_pt,
27230 Vector<Vector<std::map<unsigned,FiniteElement*> > >
27231 &received_old_haloed_element_pt,
27232 Vector<FiniteElement*> &new_elements_on_domain,
27233 Vector<Node*> &new_nodes_on_domain,
27234 Vector<Vector<Vector<std::map<unsigned, Node*> > > >
27235 &other_proc_shd_bnd_node_pt,
27236 Vector<Vector<Vector<unsigned> > > &global_node_names,
27237 std::map<Vector<unsigned>,
unsigned> &node_name_to_global_index,
27238 Vector<Node*> &global_shared_node_pt)
27240 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27241 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27242 <<
" Bool: New element needs to be constructed "
27243 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27247 if (Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++]==1)
27251 GeneralisedElement *new_el_pt=
new ELEMENT;
27258 FiniteElement* f_el_pt=
dynamic_cast<FiniteElement*
>(new_el_pt);
27261 new_elements_on_domain.push_back(f_el_pt);
27264 this->add_element_load_balance_helper(iproc,
27265 received_old_haloed_element_pt,
27269 unsigned n_node=f_el_pt->nnode();
27270 for (
unsigned j=0;j<n_node;j++)
27272 Node* new_nod_pt=0;
27275 add_received_node_load_balance_helper(new_nod_pt,
27277 received_old_haloed_element_pt,
27278 new_nodes_on_domain,
27279 other_proc_shd_bnd_node_pt,
27282 node_name_to_global_index,
27283 global_shared_node_pt);
27288 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27290 <<
"Rec:" << Counter_for_flat_packed_unsigneds
27291 <<
" Index of existing element "
27292 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27297 Counter_for_flat_packed_unsigneds++;
27310 template<
class ELEMENT>
27313 Vector<Vector<std::map<
27314 unsigned,FiniteElement*> > >
27315 &received_old_haloed_element_pt,
27316 FiniteElement* ele_pt)
27319 const unsigned nproc = this->communicator_pt()->nproc();
27321 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27322 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27323 <<
" Bool: Element is associated to a boundary "
27324 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27329 const unsigned is_on_original_boundary =
27330 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27331 if (is_on_original_boundary == 1)
27333 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27335 <<
"Rec:" << Counter_for_flat_packed_unsigneds
27336 <<
" How many boundaries are associated with the element "
27337 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27341 const unsigned nassociated_boundaries =
27342 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27345 for (
unsigned b = 0; b < nassociated_boundaries; b++)
27347 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27349 <<
"Rec:" << Counter_for_flat_packed_unsigneds
27350 <<
" Boundary associated to the element "
27351 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27356 const unsigned bnd =
27357 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27359 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27361 <<
"Rec:" << Counter_for_flat_packed_unsigneds
27362 <<
" Face index of the element "
27363 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27368 const unsigned face_index =
27369 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27373 this->Boundary_element_pt[bnd].push_back(ele_pt);
27374 this->Face_index_at_boundary[bnd].push_back(face_index);
27379 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27380 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27381 <<
" Bool: Element is associated to a boundary-region "
27382 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27387 if (Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++]==1)
27389 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27391 <<
"Rec:" << Counter_for_flat_packed_unsigneds
27392 <<
" How many boundaries-regions are associated with the element "
27393 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27397 const unsigned nassociated_boundaries_and_regions =
27398 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27400 for (
unsigned br = 0; br < nassociated_boundaries_and_regions; br++)
27402 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27404 <<
"Rec:" << Counter_for_flat_packed_unsigneds
27405 <<
" Boundary associated to the element "
27406 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27410 const unsigned bnd =
27411 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27413 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27415 <<
"Rec:" << Counter_for_flat_packed_unsigneds
27416 <<
" Region associated to the element "
27417 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27421 const unsigned region =
27422 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27424 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27426 <<
"Rec:" << Counter_for_flat_packed_unsigneds
27427 <<
" Face index of the element in boundary-region "
27428 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27431 const unsigned face_index =
27432 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27436 this->Boundary_region_element_pt[bnd][region].push_back(ele_pt);
27437 this->Face_index_region_at_boundary[bnd][region].push_back(face_index);
27447 if (is_on_original_boundary != 0)
27449 std::ostringstream error_message;
27451 <<
"The current element is not on an original boundary, this should\n"
27452 <<
"be indicated by a zero flag. However, the read value for\n"
27453 <<
"that flag is ("<<is_on_original_boundary<<
").\n\n";
27454 throw OomphLibError(
27455 error_message.str(),
27456 "RefineableTriangleMesh::add_element_load_balance_helper()",
27457 OOMPH_EXCEPTION_LOCATION);
27462 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27463 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27464 <<
" Bool: Element is associated to a shared boundary "
27465 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27470 const unsigned is_on_shared_boundary =
27471 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27472 if (is_on_shared_boundary == 3)
27474 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27476 <<
"Rec:" << Counter_for_flat_packed_unsigneds
27477 <<
" How many shared boundaries are associated with the element "
27478 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27483 const unsigned nassociated_shared_boundaries =
27484 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27487 for (
unsigned b = 0; b < nassociated_shared_boundaries; b++)
27489 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27491 <<
"Rec:" << Counter_for_flat_packed_unsigneds
27492 <<
" Shared boundary associated to the element "
27493 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27496 const unsigned bnd =
27497 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27499 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27501 <<
"Rec:" << Counter_for_flat_packed_unsigneds
27502 <<
" Face index of the element associated to the shared boundary "
27503 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27507 const unsigned face_index =
27508 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27510 this->add_shared_boundary_element(bnd, ele_pt);
27511 this->add_face_index_at_shared_boundary(bnd, face_index);
27519 if (is_on_shared_boundary != 0)
27521 std::ostringstream error_message;
27523 <<
"The current element is not on a shared boundary, this should\n"
27524 <<
"be indicated by a zero flag. However, the read value for\n"
27525 <<
"that flag is ("<<is_on_shared_boundary<<
").\n\n";
27526 throw OomphLibError(
27527 error_message.str(),
27528 "RefineableTriangleMesh::add_element_load_balance_helper()",
27529 OOMPH_EXCEPTION_LOCATION);
27538 for (
unsigned jproc = 0; jproc < nproc; jproc++)
27540 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27541 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27542 <<
" Bool: Number of haloed indexes of the element with the "
27543 << jproc <<
" processor: "
27544 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27548 const unsigned n_index_haloed_jproc =
27549 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27551 for (
unsigned ihd = 0; ihd < n_index_haloed_jproc; ihd++)
27553 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27554 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27555 <<
" Bool: The haloed element index with the "
27556 << jproc <<
" processor: "
27557 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27560 const unsigned haloed_index =
27561 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27564 received_old_haloed_element_pt[iproc][jproc][haloed_index] = ele_pt;
27575 template <
class ELEMENT>
27578 Vector<Vector<FiniteElement*> >
27580 Vector<Vector<std::map<
27581 unsigned,FiniteElement*> > >
27582 &received_old_haloed_element_pt,
27583 Vector<Node*> &new_nodes_on_domain,
27584 Vector<Vector<Vector<
27585 std::map<unsigned, Node*> > > >
27586 &other_proc_shd_bnd_node_pt,
27588 unsigned& node_index,
27589 FiniteElement*
const &new_el_pt,
27590 Vector<Vector<Vector<unsigned> > >
27591 &global_node_names,
27592 std::map<Vector<unsigned>,
unsigned>
27593 &node_name_to_global_index,
27594 Vector<Node*> &global_shared_node_pt)
27598 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27599 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27600 <<
" Bool: New node needs to be constructed "
27601 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27604 if (Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++]==1)
27608 construct_new_node_load_balance_helper(new_nod_pt,
27610 received_old_haloed_element_pt,
27611 new_nodes_on_domain,
27612 other_proc_shd_bnd_node_pt,
27617 node_name_to_global_index,
27618 global_shared_node_pt);
27622 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27623 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27624 <<
" Index of existing halo node "
27625 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27631 new_nod_pt = new_nodes_on_domain[
27632 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++]];
27635 new_el_pt->node_pt(node_index) = new_nod_pt;
27646 template<
class ELEMENT>
27650 Vector<Vector<FiniteElement*> > &f_haloed_ele_pt,
27651 Vector<Vector<std::map<unsigned,FiniteElement*> > >
27652 &received_old_haloed_element_pt,
27653 Vector<Node*> &new_nodes_on_domain,
27654 Vector<Vector<Vector<std::map<unsigned, Node*> > > >
27655 &other_proc_shd_bnd_node_pt,
27656 unsigned& iproc,
unsigned& node_index,
27657 FiniteElement*
const &new_el_pt,
27658 Vector<Vector<Vector<unsigned> > > &global_node_names,
27659 std::map<Vector<unsigned>,
unsigned> &node_name_to_global_index,
27660 Vector<Node*> &global_shared_node_pt)
27663 const unsigned nproc = this->communicator_pt()->nproc();
27665 const unsigned my_rank = this->communicator_pt()->my_rank();
27669 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27670 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27671 <<
" Number of values of external halo node "
27672 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27675 unsigned n_val=Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27678 TimeStepper* time_stepper_pt=this->Time_stepper_pt;
27680 unsigned n_prev=time_stepper_pt->ntstorage();
27684 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27685 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27686 <<
" Is the node on an original boundary "
27687 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27692 const unsigned node_on_original_boundaries =
27693 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27696 Vector<unsigned> original_boundaries_node_is_on;
27698 Vector<double> zeta_coordinates;
27700 unsigned n_original_boundaries_node_is_on = 0;
27702 if (node_on_original_boundaries==2)
27705 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27706 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27707 <<
" Number of boundaries the node is on: "
27708 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27711 n_original_boundaries_node_is_on =
27712 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27715 original_boundaries_node_is_on.resize(n_original_boundaries_node_is_on);
27716 zeta_coordinates.resize(n_original_boundaries_node_is_on);
27718 for (
unsigned i=0;i<n_original_boundaries_node_is_on;i++)
27721 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27722 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27723 <<
" Node is on boundary "
27724 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27727 original_boundaries_node_is_on[i] =
27728 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27729 zeta_coordinates[i] =
27730 Flat_packed_doubles[Counter_for_flat_packed_doubles++];
27737 if (node_on_original_boundaries != 0)
27739 std::ostringstream error_message;
27741 <<
"The current node is not on an original boundary, this should\n"
27742 <<
"be indicated by a zero flag. However, the read value for\n"
27743 <<
"that flag is ("<<node_on_original_boundaries<<
").\n\n";
27744 throw OomphLibError(
27745 error_message.str(),
27746 "RefineableTriangleMesh::construct_new_halo_node_helper()",
27747 OOMPH_EXCEPTION_LOCATION);
27755 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27756 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27757 <<
" Is node on shared boundary? "
27758 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27761 const unsigned is_node_on_shared_boundary =
27762 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27763 if (is_node_on_shared_boundary == 1)
27766 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27767 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27768 <<
" Number of boundaries the node is on: "
27769 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27772 const unsigned n_shd_bnd_node_is_on =
27773 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27774 Vector<unsigned> shd_bnds_node_is_on(n_shd_bnd_node_is_on);
27775 for (
unsigned i=0;i<n_shd_bnd_node_is_on;i++)
27778 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27779 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27780 <<
" Node is on boundary "
27781 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27784 shd_bnds_node_is_on[i] =
27785 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27789 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27790 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27791 <<
" Index of node on boundary "
27792 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27796 unsigned node_index_on_shared_boundary =
27797 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27801 this->sorted_shared_boundary_node_pt(shd_bnds_node_is_on[0],
27802 node_index_on_shared_boundary);
27808 if (is_node_on_shared_boundary != 0)
27810 std::ostringstream error_message;
27812 <<
"The current node is not on a shared boundary, this should\n"
27813 <<
"be indicated by a zero flag. However, the read value for\n"
27814 <<
"that flag is ("<<is_node_on_shared_boundary<<
").\n\n";
27815 throw OomphLibError(
27816 error_message.str(),
27817 "RefineableTriangleMesh::construct_new_halo_node_helper()",
27818 OOMPH_EXCEPTION_LOCATION);
27825 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27826 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27827 <<
" Is the node on shared boundaries with other processors "
27828 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27834 const unsigned is_the_node_in_shared_boundaries_with_other_processors =
27835 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27838 Vector<unsigned> other_processor_1;
27839 Vector<unsigned> other_processor_2;
27840 Vector<unsigned> other_shared_boundaries;
27841 Vector<unsigned> other_indexes;
27844 unsigned n_shd_bnd_with_other_procs_have_node = 0;
27847 if (is_the_node_in_shared_boundaries_with_other_processors == 4)
27849 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27850 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27851 <<
" In how many shared boundaries with other "
27852 <<
"processors is the node "
27853 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27858 n_shd_bnd_with_other_procs_have_node =
27859 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27862 other_processor_1.resize(n_shd_bnd_with_other_procs_have_node);
27863 other_processor_2.resize(n_shd_bnd_with_other_procs_have_node);
27864 other_shared_boundaries.resize(n_shd_bnd_with_other_procs_have_node);
27865 other_indexes.resize(n_shd_bnd_with_other_procs_have_node);
27867 for (
unsigned i = 0; i < n_shd_bnd_with_other_procs_have_node; i++)
27869 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27870 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27871 <<
" Processor where the other shared boundary"
27873 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27877 other_processor_1[i] =
27878 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27880 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27881 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27882 <<
" Processor where the other shared boundary"
27884 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27888 other_processor_2[i] =
27889 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27891 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27892 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27893 <<
" Other shared boundary id where the node is on: "
27894 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27899 other_shared_boundaries[i] =
27900 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27902 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27903 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27904 <<
" Node index on the other shared boundary "
27905 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27911 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27919 if (is_the_node_in_shared_boundaries_with_other_processors != 0)
27921 std::ostringstream error_message;
27923 <<
"The current node is not on a shared boundary with\n"
27924 <<
"other processors, this should be indicated by a zero flag.\n"
27925 <<
"However, the read value for that flag is ("
27926 <<is_the_node_in_shared_boundaries_with_other_processors<<
").\n\n";
27927 throw OomphLibError(
27928 error_message.str(),
27929 "RefineableTriangleMesh::construct_new_node_load_balance_helper()",
27930 OOMPH_EXCEPTION_LOCATION);
27940 Vector<Vector<unsigned> > halo_element_number(nproc);
27942 Vector<Vector<unsigned> > halo_node_number_in_halo_element(nproc);
27945 for (
unsigned jproc = 0; jproc < nproc; jproc++)
27947 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27948 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27949 <<
" The node is on "
27950 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27951 <<
" halo elements with " << jproc <<
" processor"
27956 const unsigned n_jproc_halo_ele_node_is_on =
27957 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27960 halo_element_number[jproc].resize(n_jproc_halo_ele_node_is_on);
27961 halo_node_number_in_halo_element[jproc].resize(n_jproc_halo_ele_node_is_on);
27966 for (
unsigned i = 0; i < n_jproc_halo_ele_node_is_on; i++)
27969 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27970 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27971 <<
" The halo element index where the node is on "
27972 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27976 const unsigned halo_ele_index =
27977 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27978 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27979 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
27980 <<
" The node index on the halo element where the node "
27982 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
27985 const unsigned node_index_on_halo_ele =
27986 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
27989 halo_element_number[jproc][i] = halo_ele_index;
27991 halo_node_number_in_halo_element[jproc][i] = node_index_on_halo_ele;
28000 std::set<Node*> set_haloed_node_pt;
28003 Node* haloed_node_pt = 0;
28009 bool on_haloed_element_with_iproc_processor =
false;
28010 if (halo_element_number[my_rank].size() > 0)
28014 on_haloed_element_with_iproc_processor =
true;
28017 const unsigned n_haloed_indexes = halo_element_number[my_rank].size();
28021 for (
unsigned i = 0; i < n_haloed_indexes; i++)
28024 const unsigned haloed_index = halo_element_number[my_rank][i];
28026 const unsigned haloed_node_index =
28027 halo_node_number_in_halo_element[my_rank][i];
28030 FiniteElement* tmp_haloed_ele_pt = f_haloed_ele_pt[iproc][haloed_index];
28032 Node* tmp_haloed_node_pt = tmp_haloed_ele_pt->node_pt(haloed_node_index);
28035 haloed_node_pt = tmp_haloed_node_pt;
28038 set_haloed_node_pt.insert(tmp_haloed_node_pt);
28041 if (set_haloed_node_pt.size() > 1)
28043 std::ostringstream error_message;
28045 <<
"When adding the " << haloed_node_index <<
" node of the "
28046 << haloed_index <<
"-th haloed element\n"
28047 <<
"in the currrent processor with the " << iproc <<
" processor"
28048 <<
"it was found that\nthe node pointer is different from the other"
28049 <<
"instances of the node.\nIt means we have a repeated node."
28050 <<
"This are the node coordinates of the previous node instances\n"
28051 <<
"The last entry is for the just added node with a different node\n"
28053 for (std::set<Node*>::iterator it = set_haloed_node_pt.begin();
28054 it != set_haloed_node_pt.end(); it++)
28057 <<
"Node: ("<< (*it)->x(0)<<
", "<<(*it)->x(1)<<
")\n";
28059 error_message <<
"\n";
28060 throw OomphLibError(
28061 error_message.str(),
28062 "RefineableTriangleMesh::construct_new_node_load_balance_helper()",
28063 OOMPH_EXCEPTION_LOCATION);
28073 bool found_on_haloed_element_with_other_processor =
false;
28076 for (
unsigned jproc = 0; jproc < iproc; jproc++)
28079 if (halo_element_number[jproc].size() > 0)
28082 const unsigned n_halo_indexes = halo_element_number[jproc].size();
28086 for (
unsigned i = 0; i < n_halo_indexes; i++)
28089 const unsigned haloed_index = halo_element_number[jproc][i];
28091 const unsigned haloed_node_index =
28092 halo_node_number_in_halo_element[jproc][i];
28096 std::map<unsigned,FiniteElement*>::iterator it_map =
28097 received_old_haloed_element_pt[jproc][iproc].find(haloed_index);
28099 if (it_map != received_old_haloed_element_pt[jproc][iproc].end())
28104 found_on_haloed_element_with_other_processor =
true;
28107 FiniteElement* tmp_haloed_ele_pt = (*it_map).second;
28109 Node* tmp_haloed_node_pt =
28110 tmp_haloed_ele_pt->node_pt(haloed_node_index);
28113 haloed_node_pt = tmp_haloed_node_pt;
28116 set_haloed_node_pt.insert(tmp_haloed_node_pt);
28119 if (set_haloed_node_pt.size() > 1)
28121 std::ostringstream error_message;
28123 <<
"When adding the " << haloed_node_index <<
" node of the "
28124 << haloed_index <<
"-th haloed element "
28125 <<
"of the " << jproc <<
" processor\nwith the "
28126 << iproc <<
" processor, it was found that\n"
28127 <<
"the node pointer is different from the other\n"
28128 <<
"instances of the node.\nThis means we have a repeated node.\n"
28129 <<
"These are the node coordinates of the previous node "
28131 <<
"The last entry is for the just added node with a different\n"
28132 <<
"node pointer\n";
28133 for (std::set<Node*>::iterator it = set_haloed_node_pt.begin();
28134 it != set_haloed_node_pt.end(); it++)
28137 <<
"Node: ("<< (*it)->x(0)<<
", "<<(*it)->x(1)<<
")\n";
28139 error_message <<
"\n";
28140 throw OomphLibError(
28141 error_message.str(),
28142 "RefineableTriangleMesh::construct_new_node_load_balance_helper()",
28143 OOMPH_EXCEPTION_LOCATION);
28161 if (on_haloed_element_with_iproc_processor ||
28162 found_on_haloed_element_with_other_processor)
28165 new_nod_pt = haloed_node_pt;
28173 if (is_node_on_shared_boundary == 1 ||
28174 (on_haloed_element_with_iproc_processor))
28179 if (node_on_original_boundaries==2)
28185 for (
unsigned i = 0; i < n_original_boundaries_node_is_on; i++)
28187 add_boundary_node(original_boundaries_node_is_on[i], new_nod_pt);
28189 Vector<double> zeta(1);
28190 zeta[0] = zeta_coordinates[i];
28191 new_nod_pt->set_coordinates_on_boundary(
28192 original_boundaries_node_is_on[i],zeta);
28198 new_nodes_on_domain.push_back(new_nod_pt);
28201 new_el_pt->node_pt(node_index) = new_nod_pt;
28211 bool found_node_in_other_shared_boundaries =
false;
28220 bool build_node_as_boundary_node =
false;
28222 if (is_the_node_in_shared_boundaries_with_other_processors == 4)
28225 build_node_as_boundary_node =
true;
28232 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
28236 Vector<Node*> found_node_pt;
28239 for (
unsigned i = 0; i < n_shd_bnd_with_other_procs_have_node; i++)
28241 unsigned oproc1 = other_processor_1[i];
28242 unsigned oproc2 = other_processor_2[i];
28246 if (oproc1 > oproc2)
28249 oproc1 = other_processor_2[i];
28254 const unsigned shd_bnd_id =
28255 other_shared_boundaries[i] - initial_shd_bnd_id;
28257 const unsigned index = other_indexes[i];
28261 const unsigned n_nodes_on_other_processor =
28262 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].size();
28264 if (n_nodes_on_other_processor > 0)
28268 std::map<unsigned, Node*>::iterator it =
28269 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].
28274 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].end())
28277 found_node_in_other_shared_boundaries =
true;
28279 Node* tmp_node_pt =
28280 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id][index];
28281 found_node_pt.push_back(tmp_node_pt);
28291 if (found_node_in_other_shared_boundaries)
28294 const unsigned ntimes_node_found = found_node_pt.size();
28295 for (
unsigned j = 1; j < ntimes_node_found; j++)
28297 if (found_node_pt[j-1] != found_node_pt[j])
28299 std::ostringstream error_message;
28301 <<
"The instances of the node that was found to be on a\n"
28302 <<
"shared boundary with other processors are not the same,\n"
28303 <<
"the coordinates for the nodes are these:\n"
28304 <<
"(" << found_node_pt[j-1]->x(0) <<
", "
28305 << found_node_pt[j-1]->x(1) <<
")\n"
28306 <<
"(" << found_node_pt[j]->x(0) <<
", "
28307 << found_node_pt[j]->x(1) <<
")\n"
28308 <<
"Not be surprised if they are the same since the node is\n"
28310 throw OomphLibError(
28311 error_message.str(),
28312 "RefineableTriangleMesh::construct_new_halo_node_helper()",
28313 OOMPH_EXCEPTION_LOCATION);
28324 if (is_node_on_shared_boundary == 1)
28329 if (found_node_pt[0] != new_nod_pt)
28331 std::ostringstream error_message;
28333 <<
"The pointer of the node that was found to be on a\n"
28334 <<
"shared boundary with other processor(s) and the pointer\n"
28335 <<
"of the node on shared boundary with the receiver\n"
28336 <<
"processor (iproc) are not the same. This means we have a\n"
28337 <<
"repeated node)\n"
28338 <<
"The coordinates for the nodes are:\n"
28339 <<
"(" << found_node_pt[0]->x(0) <<
", "
28340 << found_node_pt[0]->x(1) <<
")\n"
28341 <<
"(" << new_nod_pt->x(0) <<
", "
28342 << new_nod_pt->x(1) <<
")\n"
28343 <<
"Not to be surprised if they are the same since the node is\n"
28345 throw OomphLibError(
28346 error_message.str(),
28347 "RefineableTriangleMesh::construct_new_halo_node_helper()",
28348 OOMPH_EXCEPTION_LOCATION);
28357 new_nod_pt = found_node_pt[0];
28369 if (is_node_on_shared_boundary != 1 &&
28370 !on_haloed_element_with_iproc_processor)
28384 if (node_on_original_boundaries==2 || build_node_as_boundary_node)
28390 if (!found_node_in_other_shared_boundaries ||
28391 !found_on_haloed_element_with_other_processor)
28394 if (time_stepper_pt!=0)
28396 new_nod_pt=new_el_pt->construct_boundary_node(node_index,
28401 new_nod_pt=new_el_pt->construct_boundary_node(node_index);
28409 new_el_pt->node_pt(node_index) = new_nod_pt;
28414 for (
unsigned i = 0; i < n_original_boundaries_node_is_on; i++)
28416 add_boundary_node(original_boundaries_node_is_on[i], new_nod_pt);
28418 Vector<double> zeta(1);
28419 zeta[0] = zeta_coordinates[i];
28420 new_nod_pt->set_coordinates_on_boundary(
28421 original_boundaries_node_is_on[i],zeta);
28431 if (!found_node_in_other_shared_boundaries ||
28432 !found_on_haloed_element_with_other_processor)
28435 if (time_stepper_pt!=0)
28437 new_nod_pt=new_el_pt->construct_node(node_index, time_stepper_pt);
28441 new_nod_pt=new_el_pt->construct_node(node_index);
28448 new_el_pt->node_pt(node_index) = new_nod_pt;
28460 new_nodes_on_domain.push_back(new_nod_pt);
28466 if (!found_node_in_other_shared_boundaries ||
28467 !found_on_haloed_element_with_other_processor)
28470 this->add_node_pt(new_nod_pt);
28475 AlgebraicNode* new_alg_nod_pt=
dynamic_cast<AlgebraicNode*
>
28480 if (new_alg_nod_pt!=0)
28489 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28490 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28491 <<
" Alg node update id "
28492 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28496 unsigned update_id=Flat_packed_unsigneds
28497 [Counter_for_flat_packed_unsigneds++];
28499 Vector<double> ref_value;
28503 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28504 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28505 <<
" Alg node # of ref values "
28506 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28509 unsigned n_ref_val=Flat_packed_unsigneds
28510 [Counter_for_flat_packed_unsigneds++];
28514 ref_value.resize(n_ref_val);
28515 for (
unsigned i_ref=0;i_ref<n_ref_val;i_ref++)
28517 ref_value[i_ref]=Flat_packed_doubles
28518 [Counter_for_flat_packed_doubles++];
28521 Vector<GeomObject*> geom_object_pt;
28528 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28529 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28530 <<
" Alg node # of geom objects "
28531 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28534 unsigned n_geom_obj=Flat_packed_unsigneds
28535 [Counter_for_flat_packed_unsigneds++];
28539 geom_object_pt.resize(n_geom_obj);
28540 for (
unsigned i_geom=0;i_geom<n_geom_obj;i_geom++)
28542 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28543 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28544 <<
" Alg node: geom object index "
28545 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28548 unsigned geom_index=Flat_packed_unsigneds
28549 [Counter_for_flat_packed_unsigneds++];
28556 geom_object_pt[i_geom]=alg_mesh_pt->
28557 geom_object_list_pt(geom_index);
28564 if (!found_node_in_other_shared_boundaries ||
28565 !found_on_haloed_element_with_other_processor)
28569 new_alg_nod_pt->add_node_update_info
28570 (update_id,alg_mesh_pt,geom_object_pt,ref_value);
28573 alg_mesh_pt->update_node_update(new_alg_nod_pt);
28584 if (!found_node_in_other_shared_boundaries ||
28585 !found_on_haloed_element_with_other_processor)
28588 MacroElementNodeUpdateNode* macro_nod_pt=
28589 dynamic_cast<MacroElementNodeUpdateNode*
>(new_nod_pt);
28591 if (macro_nod_pt!=0)
28595 Vector<GeomObject*> geom_object_vector_pt;
28599 MacroElementNodeUpdateMesh* macro_mesh_pt=
28600 dynamic_cast<MacroElementNodeUpdateMesh*
>(
this);
28601 geom_object_vector_pt=
28602 macro_mesh_pt->geom_object_vector_pt();
28605 Vector<double> s_in_macro_node_update_element;
28606 new_el_pt->local_coordinate_of_node
28607 (node_index,s_in_macro_node_update_element);
28610 macro_nod_pt->set_node_update_info
28611 (new_el_pt,s_in_macro_node_update_element,
28612 geom_object_vector_pt);
28619 unsigned n_new_val=new_nod_pt->nvalue();
28625 if (!found_node_in_other_shared_boundaries ||
28626 !found_on_haloed_element_with_other_processor)
28628 if (n_val>n_new_val)
28635 BoundaryNodeBase *bnod_pt =
28636 dynamic_cast<BoundaryNodeBase*
>(new_nod_pt);
28641 if(bnod_pt->index_of_first_value_assigned_by_face_element_pt()==0)
28643 bnod_pt->index_of_first_value_assigned_by_face_element_pt()=
28644 new std::map<unsigned, unsigned>;
28648 std::map<unsigned, unsigned>* map_pt=
28649 bnod_pt->index_of_first_value_assigned_by_face_element_pt();
28653 const unsigned id_face = 0;
28655 std::map<unsigned, unsigned>::const_iterator p=map_pt->find(id_face);
28658 if(p==map_pt->end())
28662 (*map_pt)[id_face] = n_new_val;
28665 new_nod_pt->resize(n_val);
28674 SolidNode* solid_nod_pt=
dynamic_cast<SolidNode*
>(new_nod_pt);
28675 if (solid_nod_pt!=0)
28677 unsigned n_solid_val=solid_nod_pt->variable_position_pt()->nvalue();
28678 for (
unsigned i_val=0;i_val<n_solid_val;i_val++)
28680 for (
unsigned t=0;
t<n_prev;
t++)
28683 Flat_packed_doubles[Counter_for_flat_packed_doubles++];
28689 if (!found_node_in_other_shared_boundaries ||
28690 !found_on_haloed_element_with_other_processor)
28692 solid_nod_pt->variable_position_pt()->
28693 set_value(
t, i_val, read_data);
28701 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28702 oomph_info <<
"Rec:" << Counter_for_flat_packed_unsigneds
28703 <<
" Number of values solid node: "
28704 << Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds]
28707 const unsigned nvalues_solid_node =
28708 Flat_packed_unsigneds[Counter_for_flat_packed_unsigneds++];
28709 Vector<double> values_solid_node(nvalues_solid_node);
28710 for (
unsigned i = 0; i < nvalues_solid_node; i++)
28712 values_solid_node[i] =
28713 Flat_packed_doubles[Counter_for_flat_packed_doubles++];
28720 if (!found_node_in_other_shared_boundaries ||
28721 !found_on_haloed_element_with_other_processor)
28723 unsigned index = 0;
28724 solid_nod_pt->read_values_from_vector(values_solid_node, index);
28732 for (
unsigned i_val=0;i_val<n_val;i_val++)
28734 for (
unsigned t=0;
t<n_prev;
t++)
28737 Flat_packed_doubles[Counter_for_flat_packed_doubles++];
28743 if (!found_node_in_other_shared_boundaries ||
28744 !found_on_haloed_element_with_other_processor)
28746 new_nod_pt->set_value(
t, i_val, read_data);
28755 unsigned n_dim=new_nod_pt->ndim();
28756 for (
unsigned idim=0;idim<n_dim;idim++)
28758 for (
unsigned t=0;
t<n_prev;
t++)
28761 Flat_packed_doubles[Counter_for_flat_packed_doubles++];
28767 if (!found_node_in_other_shared_boundaries ||
28768 !found_on_haloed_element_with_other_processor)
28771 new_nod_pt->x(
t,idim) = read_data;
28784 if (n_shd_bnd_with_other_procs_have_node > 0 &&
28788 !found_node_in_other_shared_boundaries)
28797 this->update_other_proc_shd_bnd_node_helper(new_nod_pt,
28798 other_proc_shd_bnd_node_pt,
28801 other_shared_boundaries,
28804 node_name_to_global_index,
28805 global_shared_node_pt);
28811 #endif // #ifdef OOMPH_HAS_MPI
28819 template <
class ELEMENT>
28821 const unsigned &b, Vector<Vector<Node*> > &tmp_segment_nodes)
28824 tmp_segment_nodes.clear();
28827 Vector<FiniteElement*> face_el_pt;
28834 unsigned n_repeated_ele = 0;
28837 const unsigned n_regions = this->nregion();
28840 Vector < std::pair<Node*, Node *> > done_nodes_pt;
28845 for (
unsigned rr = 0 ; rr < n_regions; rr++)
28847 const unsigned region_id =
28848 static_cast<unsigned>(this->Region_attribute[rr]);
28851 const unsigned nel_in_region =
28852 this->nboundary_element_in_region(b, region_id);
28855 unsigned nel_repeated_in_region = 0;
28859 if (nel_in_region > 0)
28863 bool repeated =
false;
28866 for (
unsigned e = 0; e < nel_in_region; e++)
28869 FiniteElement* bulk_elem_pt =
28870 this->boundary_element_in_region_pt(b, region_id, e);
28872 #ifdef OOMPH_HAS_MPI
28874 if (this->is_mesh_distributed() && bulk_elem_pt->is_halo())
28885 this->face_index_at_boundary_in_region(b, region_id, e);
28890 FiniteElement* tmp_ele_pt =
new DummyFaceElement<ELEMENT> (
28891 bulk_elem_pt, face_index);
28894 const unsigned n_nodes = tmp_ele_pt->nnode();
28896 std::pair<Node*, Node*> tmp_pair =
28897 std::make_pair(tmp_ele_pt->node_pt(0),
28898 tmp_ele_pt->node_pt(n_nodes - 1));
28900 std::pair<Node*, Node*> tmp_pair_inverse =
28901 std::make_pair(tmp_ele_pt->node_pt(n_nodes - 1),
28902 tmp_ele_pt->node_pt(0));
28905 unsigned n_done_nodes = done_nodes_pt.size();
28906 for (
unsigned l = 0; l < n_done_nodes; l++)
28908 if (tmp_pair == done_nodes_pt[l] || tmp_pair_inverse
28909 == done_nodes_pt[l])
28911 nel_repeated_in_region++;
28922 done_nodes_pt.push_back(tmp_pair);
28924 face_el_pt.push_back(tmp_ele_pt);
28940 nel += nel_in_region;
28943 n_repeated_ele += nel_repeated_in_region;
28954 nel = this->nboundary_element(b);
28961 bool repeated =
false;
28964 for (
unsigned e = 0; e < nel; e++)
28967 FiniteElement* bulk_elem_pt = this->boundary_element_pt(b, e);
28969 #ifdef OOMPH_HAS_MPI
28971 if (this->is_mesh_distributed() && bulk_elem_pt->is_halo())
28981 int face_index = this->face_index_at_boundary(b, e);
28985 FiniteElement* tmp_ele_pt =
new DummyFaceElement<ELEMENT> (
28986 bulk_elem_pt, face_index);
28989 const unsigned n_nodes = tmp_ele_pt->nnode();
28991 std::pair<Node*, Node*> tmp_pair =
28992 std::make_pair(tmp_ele_pt->node_pt(0),
28993 tmp_ele_pt->node_pt(n_nodes - 1));
28995 std::pair<Node*, Node*> tmp_pair_inverse =
28996 std::make_pair(tmp_ele_pt->node_pt(n_nodes - 1),
28997 tmp_ele_pt->node_pt(0));
29000 unsigned n_done_nodes = done_nodes_pt.size();
29001 for (
unsigned l = 0; l < n_done_nodes; l++)
29003 if (tmp_pair == done_nodes_pt[l] || tmp_pair_inverse
29004 == done_nodes_pt[l])
29017 done_nodes_pt.push_back(tmp_pair);
29019 face_el_pt.push_back(tmp_ele_pt);
29038 nel -= n_repeated_ele;
29041 if (nel!=face_el_pt.size())
29043 std::ostringstream error_message;
29045 <<
"The independet counting of face elements ("<<nel<<
") for "
29046 <<
"boundary ("<<b<<
") is different\n"
29047 <<
"from the real number of face elements in the container ("
29048 << face_el_pt.size() <<
")\n";
29049 throw OomphLibError(error_message.str(),
29050 "RefineableTriangleMesh::get_boundary_segment_nodes_helper()",
29051 OOMPH_EXCEPTION_LOCATION);
29059 const unsigned nnon_halo_face_elements = nel;
29063 Vector<std::list<FiniteElement*> > segment_sorted_ele_pt;
29067 unsigned nsorted_face_elements = 0;
29071 std::map<FiniteElement*, bool> done_ele;
29076 std::map<FiniteElement*, bool> is_inverted;
29081 while(nsorted_face_elements < nnon_halo_face_elements)
29085 std::list<FiniteElement*> sorted_el_pt;
29089 bool found_initial_face_element =
false;
29092 FiniteElement* ele_face_pt = 0;
29094 unsigned iface = 0;
29095 #ifdef OOMPH_HAS_MPI
29096 if (this->is_mesh_distributed())
29098 for (iface = 0; iface < nel; iface++)
29100 ele_face_pt = face_el_pt[iface];
29102 if (!done_ele[ele_face_pt])
29107 found_initial_face_element =
true;
29110 nsorted_face_elements++;
29114 sorted_el_pt.push_back(ele_face_pt);
29116 done_ele[ele_face_pt] =
true;
29123 #endif // #ifdef OOMPH_HAS_MPI
29127 ele_face_pt = face_el_pt[0];
29130 found_initial_face_element =
true;
29133 nsorted_face_elements++;
29137 sorted_el_pt.push_back(ele_face_pt);
29139 done_ele[ele_face_pt] =
true;
29140 #ifdef OOMPH_HAS_MPI
29145 if (!found_initial_face_element)
29147 std::ostringstream error_message;
29149 <<
"Could not find an initial face element for the current segment\n";
29150 throw OomphLibError(error_message.str(),
29151 "RefineableTriangleMesh::get_boundary_segment_nodes_helper()",
29152 OOMPH_EXCEPTION_LOCATION);
29157 const unsigned nnod = ele_face_pt->nnode();
29161 Node* left_node_pt = ele_face_pt->node_pt(0);
29162 Node* right_node_pt = ele_face_pt->node_pt(nnod - 1);
29166 bool face_element_added =
false;
29176 for (
unsigned iiface=iface;iiface<nel;iiface++)
29179 face_element_added =
false;
29182 ele_face_pt = face_el_pt[iiface];
29186 if (!done_ele[ele_face_pt])
29189 Node* local_left_node_pt = ele_face_pt->node_pt(0);
29190 Node* local_right_node_pt = ele_face_pt->node_pt(nnod - 1);
29193 if (left_node_pt == local_right_node_pt)
29195 left_node_pt = local_left_node_pt;
29196 sorted_el_pt.push_front(ele_face_pt);
29197 is_inverted[ele_face_pt] =
false;
29198 face_element_added =
true;
29201 else if (left_node_pt == local_left_node_pt)
29203 left_node_pt = local_right_node_pt;
29204 sorted_el_pt.push_front(ele_face_pt);
29205 is_inverted[ele_face_pt] =
true;
29206 face_element_added =
true;
29209 else if (right_node_pt == local_left_node_pt)
29211 right_node_pt = local_right_node_pt;
29212 sorted_el_pt.push_back(ele_face_pt);
29213 is_inverted[ele_face_pt] =
false;
29214 face_element_added =
true;
29217 else if (right_node_pt == local_right_node_pt)
29219 right_node_pt = local_left_node_pt;
29220 sorted_el_pt.push_back(ele_face_pt);
29221 is_inverted[ele_face_pt] =
true;
29222 face_element_added =
true;
29225 if (face_element_added)
29228 done_ele[ele_face_pt] =
true;
29229 nsorted_face_elements++;
29237 }
while(face_element_added &&
29238 (nsorted_face_elements < nnon_halo_face_elements));
29241 segment_sorted_ele_pt.push_back(sorted_el_pt);
29246 const unsigned nsegments = segment_sorted_ele_pt.size();
29249 if (nnon_halo_face_elements > 0 && nsegments == 0)
29251 std::ostringstream error_message;
29253 <<
"The number of segments is zero, but the number of nonhalo\n"
29254 <<
"elements is: (" << nnon_halo_face_elements <<
")\n";
29255 throw OomphLibError(error_message.str(),
29256 "RefineableTriangleMesh::get_boundary_segment_nodes_helper()",
29257 OOMPH_EXCEPTION_LOCATION);
29266 tmp_segment_nodes.resize(nsegments);
29268 for (
unsigned is = 0;
is < nsegments;
is++)
29271 if (segment_sorted_ele_pt[
is].size() == 0)
29273 std::ostringstream error_message;
29275 <<
"The (" <<
is <<
")-th segment has no elements\n";
29276 throw OomphLibError(error_message.str(),
29277 "RefineableTriangleMesh::get_boundary_segment_nodes_helper()",
29278 OOMPH_EXCEPTION_LOCATION);
29283 FiniteElement* first_ele_pt = segment_sorted_ele_pt[
is].front();
29286 const unsigned nnod = first_ele_pt->nnode();
29289 Node *first_node_pt = first_ele_pt->node_pt(0);
29290 if (is_inverted[first_ele_pt])
29292 first_node_pt = first_ele_pt->node_pt(nnod-1);
29296 tmp_segment_nodes[
is].push_back(first_node_pt);
29299 for (std::list<FiniteElement*>::iterator it =
29300 segment_sorted_ele_pt[
is].begin();
29301 it != segment_sorted_ele_pt[
is].end(); it++)
29304 FiniteElement* ele_pt = *it;
29307 Node* last_node_pt = 0;
29310 if (!is_inverted[ele_pt])
29312 last_node_pt = ele_pt->node_pt(nnod-1);
29316 last_node_pt = ele_pt->node_pt(0);
29320 tmp_segment_nodes[
is].push_back(last_node_pt);
29329 for (
unsigned e = 0; e < nel; e++)
29331 delete face_el_pt[e];
29343 template <
class ELEMENT>
29345 const Vector<double>& elem_error)
29347 double t_start_overall=TimingHelpers::timer();
29354 Vector<double> target_area(elem_error.size());
29355 double min_angle=compute_area_target(elem_error,
29361 bool quantised_areas=
true;
29362 if (quantised_areas)
29364 unsigned n=target_area.size();
29365 double total_area=0;
29371 #ifdef OOMPH_HAS_MPI
29372 if (this->is_mesh_distributed())
29376 double sub_area = 0.0;
29379 for (
unsigned e=0;e<n;e++)
29382 FiniteElement* ele_pt = this->finite_element_pt(e);
29383 if (!ele_pt->is_halo())
29385 sub_area+=ele_pt->size();
29390 OomphCommunicator* comm_pt = this->communicator_pt();
29393 MPI_Allreduce(&sub_area, &total_area, 1, MPI_DOUBLE, MPI_SUM,
29394 comm_pt->mpi_comm());
29398 for (
unsigned e=0;e<n;e++)
29400 total_area+=this->finite_element_pt(e)->size();
29406 #else // #ifdef OOMPH_HAS_MPI
29407 for (
unsigned e=0;e<n;e++)
29409 total_area+=this->finite_element_pt(e)->size();
29411 #endif // #ifdef OOMPH_HAS_MPI
29413 for (
unsigned e=0;e<n;e++)
29416 unsigned(ceil(log(target_area[e]/total_area)/log(1.0/3.0)))-1;
29417 double new_target_area=total_area*pow(1.0/3.0,
int(level));
29418 target_area[e]=new_target_area;
29428 unsigned n=target_area.size();
29429 double max_area=0.0;
29430 double min_area=DBL_MAX;
29431 for (
unsigned e=0;e<n;e++)
29433 if (target_area[e]>max_area) max_area=target_area[e];
29434 if (target_area[e]<min_area) min_area=target_area[e];
29449 oomph_info <<
"Maximum target area: " << max_area << std::endl;
29450 oomph_info <<
"Minimum target area: " << min_area << std::endl;
29451 oomph_info <<
"Number of elements to be refined: "
29452 << this->Nrefined << std::endl;
29453 oomph_info <<
"Number of elements to be unrefined: "
29454 << this->Nunrefined << std::endl;
29455 oomph_info <<
"Min. angle: " << min_angle << std::endl;
29457 double orig_max_area, orig_min_area;
29458 this->max_and_min_element_size(orig_max_area, orig_min_area);
29459 oomph_info <<
"Max./min. element size in original mesh: "
29460 << orig_max_area <<
" "
29461 << orig_min_area << std::endl;
29469 bool check_only=
true;
29470 bool outer_boundary_update_necessary=
false;
29471 bool inner_boundary_update_necessary=
false;
29472 bool inner_open_boundary_update_necessary=
false;
29476 const unsigned nouter=this->Outer_boundary_pt.size();
29478 if (this->is_automatic_creation_of_vertices_on_boundaries_allowed())
29481 for (
unsigned i_outer = 0; i_outer < nouter; i_outer++)
29483 outer_boundary_update_necessary=
29484 this->update_polygon_using_face_mesh(this->Outer_boundary_pt[i_outer],
29487 if (outer_boundary_update_necessary)
break;
29492 if (!outer_boundary_update_necessary)
29496 const unsigned nhole=this->Internal_polygon_pt.size();
29497 Vector<Vector<double> > internal_point_coord(nhole);
29498 inner_boundary_update_necessary=
29499 this->surface_remesh_for_inner_hole_boundaries(internal_point_coord,
29504 if (!inner_boundary_update_necessary)
29506 const unsigned n_open_polyline =
29507 this->Internal_open_curve_pt.size();
29509 for (
unsigned i = 0; i < n_open_polyline; i++)
29511 inner_open_boundary_update_necessary=
29512 this->update_open_curve_using_face_mesh(
29513 this->Internal_open_curve_pt[i], check_only);
29515 if (inner_open_boundary_update_necessary)
break;
29527 #ifdef OOMPH_HAS_MPI
29532 int adapt_this_processor = 0;
29533 if (this->is_mesh_distributed())
29536 if ( (Nrefined > 0) || (Nunrefined > max_keep_unrefined()) ||
29537 (min_angle < min_permitted_angle())
29538 || (outer_boundary_update_necessary)
29539 || (inner_boundary_update_necessary)
29540 || (inner_open_boundary_update_necessary) )
29541 {adapt_this_processor = 1;}
29544 OomphCommunicator* comm_pt = this->communicator_pt();
29547 MPI_Allreduce(&adapt_this_processor, &adapt_all, 1, MPI_INT, MPI_SUM,
29548 comm_pt->mpi_comm());
29556 if ( (Nrefined > 0) || (Nunrefined > max_keep_unrefined()) ||
29557 (min_angle < min_permitted_angle()) || (outer_boundary_update_necessary)
29558 || (inner_boundary_update_necessary)
29559 || (inner_open_boundary_update_necessary) || (adapt_all) )
29561 if (! ( (Nrefined > 0) || (Nunrefined > max_keep_unrefined()) ) )
29564 if ( (outer_boundary_update_necessary)
29565 || (inner_boundary_update_necessary)
29566 || (inner_open_boundary_update_necessary) )
29569 <<
"Mesh regeneration triggered by inaccurate interface/surface\n"
29570 <<
"representation; setting Nrefined to number of elements.\n"
29571 <<
"outer_boundary_update_necessary : "
29572 << outer_boundary_update_necessary <<
"\n"
29573 <<
"inner_boundary_update_necessary : "
29574 << inner_boundary_update_necessary <<
"\n"
29575 <<
"inner_open_boundary_update_necessary: "
29576 << inner_open_boundary_update_necessary <<
"\n";
29577 Nrefined=nelement();
29582 <<
"Mesh regeneration triggered by min angle criterion;\n"
29583 <<
"setting Nrefined to number of elements.\n";
29584 Nrefined=nelement();
29591 #ifdef OOMPH_HAS_MPI
29592 else if (this->is_mesh_distributed() &&
29593 adapt_this_processor == 0 && adapt_all > 0)
29596 <<
"Mesh regeneration triggered by (" << adapt_all <<
") processor(s) "
29597 <<
"that require(s)\n adaptation\n";
29612 add_vertices_for_non_deletion();
29617 #ifdef OOMPH_HAS_MPI
29622 if (this->is_mesh_distributed())
29624 synchronize_shared_boundary_connections();
29626 #endif // #ifdef OOMPH_HAS_MPI
29637 if (this->is_automatic_creation_of_vertices_on_boundaries_allowed())
29640 unsigned nhole=this->Internal_polygon_pt.size();
29641 Vector<Vector<double> > internal_point_coord(nhole);
29642 this->surface_remesh_for_inner_hole_boundaries(internal_point_coord);
29645 for (
unsigned i_outer = 0; i_outer < nouter; i_outer++)
29647 this->update_polygon_using_face_mesh(
29648 this->Outer_boundary_pt[i_outer]);
29653 unsigned n_open_polyline = this->Internal_open_curve_pt.size();
29654 for (
unsigned i = 0; i < n_open_polyline; i++)
29656 this->update_open_curve_using_face_mesh(
29657 this->Internal_open_curve_pt[i]);
29667 const unsigned ninternal=this->Internal_polygon_pt.size();
29668 for (
unsigned i_internal = 0; i_internal < ninternal; i_internal++)
29670 this->update_polygon_using_elements_area(
29671 this->Internal_polygon_pt[i_internal], target_area);
29676 for (
unsigned i_outer = 0; i_outer < nouter; i_outer++)
29678 this->update_polygon_using_elements_area(
29679 this->Outer_boundary_pt[i_outer], target_area);
29684 const unsigned n_open_polyline = this->Internal_open_curve_pt.size();
29685 for (
unsigned i = 0; i < n_open_polyline; i++)
29687 this->update_open_curve_using_elements_area(
29688 this->Internal_open_curve_pt[i], target_area);
29699 #ifdef OOMPH_HAS_MPI
29701 if (this->is_mesh_distributed())
29704 const unsigned my_rank = this->communicator_pt()->my_rank();
29707 const unsigned n_curves = this->nshared_boundary_curves(my_rank);
29709 for (
unsigned nc = 0; nc < n_curves; nc ++)
29712 this->update_shared_curve_using_elements_area(
29713 this->Shared_boundary_polyline_pt[my_rank][nc],
29739 const unsigned n_boundary = this->nboundary();
29741 const double t_start_first_stage_segments_connectivity =
29742 TimingHelpers::timer();
29747 #ifdef OOMPH_HAS_MPI
29750 if (this->is_mesh_distributed())
29752 this->Assigned_segments_initial_zeta_values.clear();
29754 #endif // #ifdef OOMPH_HAS_MPI
29760 for(
unsigned b=0;b<n_boundary;++b)
29765 #ifdef OOMPH_HAS_MPI
29766 if (this->is_mesh_distributed())
29773 compute_boundary_segments_connectivity_and_initial_zeta_values(b);
29781 if(this->boundary_geom_object_pt(b)==0)
29783 this->
template setup_boundary_coordinates<ELEMENT>(b);
29789 #ifdef OOMPH_HAS_MPI
29790 if (this->is_mesh_distributed())
29795 this->synchronize_boundary_coordinates(b);
29804 const double t_total_first_stage_segments_connectivity =
29805 TimingHelpers::timer() - t_start_first_stage_segments_connectivity;
29815 #ifdef OOMPH_HAS_MPI
29823 Vector<TriangleMeshPolygon *> tmp_outer_polygons_pt;
29828 Vector<TriangleMeshOpenCurve *> tmp_open_curves_pt;
29830 if (this->is_mesh_distributed())
29834 this->create_distributed_domain_representation(tmp_outer_polygons_pt,
29835 tmp_open_curves_pt);
29838 this->create_temporary_boundary_connections(tmp_outer_polygons_pt,
29839 tmp_open_curves_pt);
29853 Vector<TriangleMeshPolyLine*> resume_initial_connection_polyline_pt;
29854 Vector<TriangleMeshPolyLine*> resume_final_connection_polyline_pt;
29855 restore_boundary_connections(resume_initial_connection_polyline_pt,
29856 resume_final_connection_polyline_pt);
29862 unsigned n_region = this->nregion();
29865 for(std::map<
unsigned, Vector<double> >::iterator it =
29866 this->Regions_coordinates.begin();
29867 it!=this->Regions_coordinates.end(); ++it)
29870 Vector<double> centroid(2,0.0);
29873 unsigned region_id = it->first;
29876 oomph_info <<
"Region " << region_id <<
": "
29877 << it->second[0] <<
" " << it->second[1] <<
" ";
29880 unsigned n_region_element = this->nregion_element(region_id);
29881 if(n_region_element > 0)
29884 FiniteElement*
const elem_pt = this->region_element_pt(region_id,0);
29887 for(
unsigned n=0;n<3;n++)
29889 Node*
const nod_pt = elem_pt->node_pt(n);
29890 for(
unsigned i=0;i<2;i++) {centroid[i] += nod_pt->x(i);}
29892 for(
unsigned i=0;i<2;i++) {centroid[i] /= 3;}
29894 it->second = centroid;
29896 oomph_info <<
" , " <<
29897 it->second[0] <<
" " << it->second[1] << std::endl;
29911 SolidMesh* solid_mesh_pt=
dynamic_cast<SolidMesh*
>(
this);
29921 Vector<TriangleMeshClosedCurve*> closed_curve_pt;
29922 Vector<TriangleMeshClosedCurve*> hole_pt;
29923 Vector<TriangleMeshOpenCurve*> open_curves_pt;
29925 #ifdef OOMPH_HAS_MPI
29926 if (!this->is_mesh_distributed())
29930 closed_curve_pt.resize(nouter);
29931 for (
unsigned i = 0; i < nouter; i++)
29933 closed_curve_pt[i] = this->Outer_boundary_pt[i];
29937 const unsigned n_holes = this->Internal_polygon_pt.size();
29938 hole_pt.resize(n_holes);
29939 for (
unsigned i = 0; i < n_holes; i++)
29941 hole_pt[i] = this->Internal_polygon_pt[i];
29945 const unsigned n_open_curves = this->Internal_open_curve_pt.size();
29946 open_curves_pt.resize(n_open_curves);
29947 for (
unsigned i = 0; i < n_open_curves; i++)
29949 open_curves_pt[i] = this->Internal_open_curve_pt[i];
29955 #ifdef OOMPH_HAS_MPI
29960 const unsigned n_tmp_outer = tmp_outer_polygons_pt.size();
29961 closed_curve_pt.resize(n_tmp_outer);
29962 for (
unsigned i = 0; i < n_tmp_outer; i++)
29964 closed_curve_pt[i] = tmp_outer_polygons_pt[i];
29968 const unsigned n_open_curves = tmp_open_curves_pt.size();
29969 open_curves_pt.resize(n_open_curves);
29970 for (
unsigned i = 0; i < n_open_curves; i++)
29972 open_curves_pt[i] = tmp_open_curves_pt[i];
30002 this->Extra_holes_coordinates;
30006 this->Regions_coordinates;
30009 if (this->Use_attributes)
30015 if (!this->is_automatic_creation_of_vertices_on_boundaries_allowed())
30022 #ifdef OOMPH_HAS_MPI
30023 if (this->is_mesh_distributed())
30034 const double t_start_building_background_mesh =
30035 TimingHelpers::timer();
30037 if (solid_mesh_pt!=0)
30040 (triangle_mesh_parameters, this->Time_stepper_pt);
30045 (triangle_mesh_parameters, this->Time_stepper_pt);
30048 if (Print_timings_level_adaptation>2)
30050 oomph_info <<
"CPU for building background mesh: "
30051 <<TimingHelpers::timer()-t_start_building_background_mesh
30057 const double this_max_element_size = this->max_element_size();
30058 const double this_min_element_size = this->min_element_size();
30063 const double this_min_permitted_angle = this->min_permitted_angle();
30069 #ifdef OOMPH_HAS_MPI
30073 if (this->is_mesh_distributed())
30077 if (this->nshared_boundary_overlaps_internal_boundary() > 0)
30082 this->shared_boundary_overlaps_internal_boundary();
30087 this->shared_boundaries_ids();
30092 fill_boundary_elements_and_nodes_for_internal_boundaries();
30097 #endif // #ifdef OOMPH_HAS_MPI
30107 tmp_new_mesh_pt->boundary_geom_object_pt() =
30108 this->boundary_geom_object_pt();
30112 tmp_new_mesh_pt->boundary_coordinate_limits() =
30113 this->boundary_coordinate_limits();
30115 const double t_start_second_stage_segments_connectivity =
30116 TimingHelpers::timer();
30118 for (
unsigned b=0;b<n_boundary;b++)
30123 #ifdef OOMPH_HAS_MPI
30124 if (this->is_mesh_distributed())
30129 identify_boundary_segments_and_assign_initial_zeta_values(b,
this);
30138 if(tmp_new_mesh_pt->boundary_geom_object_pt(b)!=0)
30140 tmp_new_mesh_pt->template setup_boundary_coordinates<ELEMENT>(b);
30145 const double t_total_second_stage_segments_connectivity =
30146 TimingHelpers::timer() - t_start_second_stage_segments_connectivity;
30148 const double t_start_snap_nodes_bg_mesh=TimingHelpers::timer();
30152 for(
unsigned b=0;b<n_boundary;b++)
30154 this->snap_nodes_onto_boundary(tmp_new_mesh_pt,b);
30157 const double t_total_snap_nodes_bg_mesh=
30158 TimingHelpers::timer()-t_start_snap_nodes_bg_mesh;
30160 if (Print_timings_level_adaptation>2)
30162 oomph_info<<
"CPU for snapping nodes onto boundaries "
30163 <<
"(background mesh): "
30164 << t_total_snap_nodes_bg_mesh << std::endl;
30168 if(Mesh_update_fct_pt!=0)
30170 Mesh_update_fct_pt(tmp_new_mesh_pt);
30197 TriangulateIO tmp_new_triangulateio =
30198 tmp_new_mesh_pt->triangulateio_representation();
30203 bool use_eulerian_coords=
false;
30204 if (solid_mesh_pt!=0)
30206 use_eulerian_coords=
true;
30210 #ifdef OOMPH_HAS_CGAL
30213 CGALSamplePointContainerParameters cgal_params(
this);
30214 if (use_eulerian_coords)
30216 cgal_params.enable_use_eulerian_coordinates_during_setup();
30218 MeshAsGeomObject* mesh_geom_obj_pt=
new MeshAsGeomObject(&cgal_params);
30223 NonRefineableBinArrayParameters params(
this);
30224 if (use_eulerian_coords)
30226 params.enable_use_eulerian_coordinates_during_setup();
30228 Vector<unsigned> bin_dim(2);
30229 bin_dim[0]=Nbin_x_for_area_transfer;
30230 bin_dim[1]=Nbin_y_for_area_transfer;
30231 params.dimensions_of_bin_array()=bin_dim;
30232 MeshAsGeomObject* mesh_geom_obj_pt=
new MeshAsGeomObject(¶ms);
30238 std::map<GeneralisedElement*,unsigned> element_number;
30239 unsigned nelem=this->nelement();
30240 for (
unsigned e=0;e<nelem;e++)
30242 element_number[this->element_pt(e)]=e;
30245 #ifndef OOMPH_HAS_CGAL
30250 Vector<double> bin_min_target_area;
30253 NonRefineableBinArray* bin_array_pt=
30254 dynamic_cast<NonRefineableBinArray*
>(mesh_geom_obj_pt->
30255 sample_point_container_pt());
30256 if (bin_array_pt==0)
30258 throw OomphLibError(
30259 "Sample point container has to be NonRefineableBinArray",
30260 OOMPH_CURRENT_FUNCTION,
30261 OOMPH_EXCEPTION_LOCATION);
30266 unsigned max_n_entry=0;
30267 unsigned min_n_entry=UINT_MAX;
30268 unsigned tot_n_entry=0;
30269 unsigned n_empty=0;
30270 bin_array_pt->get_fill_stats(n_bin,max_n_entry,min_n_entry,
30271 tot_n_entry,n_empty);
30273 oomph_info <<
"Before bin diffusion:"
30274 <<
" nbin:("<<n_bin<<
")"
30275 <<
" nempty:("<<n_empty<<
")"
30276 <<
" min:("<<min_n_entry<<
")"
30277 <<
" max:("<<max_n_entry<<
")"
30278 <<
" average entries:("
30279 << double(tot_n_entry)/double(n_bin)<<
")"
30284 double t0_bin_diff=TimingHelpers::timer();
30285 oomph_info <<
"Going into diffusion bit...\n";
30286 bin_array_pt->fill_bin_by_diffusion();
30287 oomph_info <<
"Back from diffusion bit...\n";
30288 oomph_info <<
"Time for bin diffusion: "
30289 << TimingHelpers::timer()-t0_bin_diff
30295 unsigned max_n_entry=0;
30296 unsigned min_n_entry=UINT_MAX;
30297 unsigned tot_n_entry=0;
30298 unsigned n_empty=0;
30299 bin_array_pt->get_fill_stats(n_bin,max_n_entry,min_n_entry,
30300 tot_n_entry,n_empty);
30302 oomph_info <<
"After bin diffusion:"
30303 <<
" nbin:("<<n_bin<<
")"
30304 <<
" nempty:("<<n_empty<<
")"
30305 <<
" min:("<<min_n_entry<<
")"
30306 <<
" max:("<<max_n_entry<<
")"
30307 <<
" average entries:("
30308 << double(tot_n_entry)/double(n_bin)<<
")"
30316 double t_total_map=0.0;
30319 unsigned counter_map = 0;
30324 const std::map<unsigned,Vector<std::pair<FiniteElement*,
30325 Vector<double> > > >*
30326 bins_pt=bin_array_pt->get_all_bins_content();
30329 const unsigned n_bin=bins_pt->size();
30334 bin_min_target_area.resize(n_bin);
30335 for (
unsigned u=0;u<n_bin;u++)
30337 bin_min_target_area[u]=0.0;
30341 typedef std::map<unsigned,
30342 Vector<std::pair<FiniteElement*,
30343 Vector<double> > > >::const_iterator IT;
30344 for (IT it=bins_pt->begin();it!=bins_pt->end();it++)
30347 unsigned ib=(*it).first;
30350 const unsigned n_ele_bin = (*it).second.size();
30353 for (
unsigned ee=0;ee<n_ele_bin;ee++)
30356 GeneralisedElement* ele_pt=(*it).second[ee].first;
30357 double t_map=TimingHelpers::timer();
30358 const unsigned ele_number = element_number[ele_pt];
30359 t_total_map+=TimingHelpers::timer()-t_map;
30367 if (bin_min_target_area[ib]!=0)
30369 bin_min_target_area[ib]=
30370 std::min(bin_min_target_area[ib], target_area[ele_number]);
30374 bin_min_target_area[ib]=target_area[ele_number];
30381 oomph_info <<
"CPU for map[counter="<<counter_map<<
"]: "
30382 << t_total_map << std::endl;
30386 const bool output_bins=
false;
30389 unsigned length=bin_min_target_area.size();
30390 for (
unsigned u = 0;u<length;u++)
30392 oomph_info <<
"Bin n" << u <<
",target area: "
30393 << bin_min_target_area[u]<<std::endl;
30404 #ifdef OOMPH_HAS_MPI
30406 unsigned n_ele_need_refinement = 0;
30410 double t_total_third_stage_segments_connectivity = 0.0;
30413 double t_total_transfer_target_areas = 0.0;
30416 double t_total_limit_target_areas = 0.0;
30419 double t_total_create_new_adapted_mesh = 0.0;
30422 double t_total_snap_nodes = 0.0;
30425 double t_total_wait_other_processors = 0.0;
30426 double t_iter=TimingHelpers::timer();
30432 double t_start_transfer_target_areas=TimingHelpers::timer();
30433 double t0_loop_int_pts=TimingHelpers::timer();
30439 nelem=tmp_new_mesh_pt->nelement();
30443 Vector<double> new_transferred_target_area(nelem,0.0);
30444 for (
unsigned e=0;e<nelem;e++)
30446 ELEMENT* el_pt=
dynamic_cast<ELEMENT*
>(tmp_new_mesh_pt->element_pt(e));
30447 unsigned nint=el_pt->integral_pt()->nweight();
30448 for (
unsigned ipt=0;ipt<nint;ipt++)
30451 Vector<double>
s(2);
30452 for(
unsigned i=0;i<2;i++)
30454 s[i] = el_pt->integral_pt()->knot(ipt,i);
30457 Vector<double> x(2);
30458 el_pt->interpolated_x(
s,x);
30465 unsigned max_sample_points=
30466 Max_sample_points_for_limited_locate_zeta_during_target_area_transfer;
30467 dynamic_cast<CGALSamplePointContainer*
>(mesh_geom_obj_pt->
30468 sample_point_container_pt())->
30469 limited_locate_zeta(x,max_sample_points,
30472 if (geom_obj_pt==0)
30474 std::stringstream error_message;
30476 <<
"Limited locate zeta failed for zeta = [ "
30477 << x[0] <<
" " << x[1] <<
" ]. Makes no sense!\n";
30478 throw OomphLibError(error_message.str(),
30479 OOMPH_CURRENT_FUNCTION,
30480 OOMPH_EXCEPTION_LOCATION);
30485 FiniteElement* fe_pt=
dynamic_cast<FiniteElement*
>(geom_obj_pt);
30489 std::stringstream error_message;
30491 <<
"Cast to FE for GeomObject returned by limited locate zeta failed for zeta = [ "
30492 << x[0] <<
" " << x[1] <<
" ]. Makes no sense!\n";
30493 throw OomphLibError(error_message.str(),
30494 OOMPH_CURRENT_FUNCTION,
30495 OOMPH_EXCEPTION_LOCATION);
30501 double tg_area=target_area[element_number[fe_pt]];
30508 if (new_transferred_target_area[e]!=0)
30510 new_transferred_target_area[e]=
30511 std::min(new_transferred_target_area[e],
30516 new_transferred_target_area[e]=tg_area;
30527 bin_array_pt->get_bin(x,bin_number);
30533 std::stringstream error_message;
30535 <<
"Very odd -- we're looking for a point[ "
30536 << x[0] <<
" " << x[1] <<
" ] that's not even \n"
30537 <<
"located within the bin boundaries.\n";
30538 throw OomphLibError(error_message.str(),
30539 "RefineableTriangleMesh::adapt()",
30540 OOMPH_EXCEPTION_LOCATION);
30548 if (new_transferred_target_area[e]!=0)
30550 new_transferred_target_area[e]=
30551 std::min(new_transferred_target_area[e],
30552 bin_min_target_area[bin_number]);
30556 new_transferred_target_area[e]=bin_min_target_area[bin_number];
30569 const bool output_target_areas=
false;
30570 if (output_target_areas)
30572 unsigned length=new_transferred_target_area.size();
30573 for (
unsigned u = 0; u < length;u++)
30575 oomph_info <<
"Element" << u <<
",target area: "
30576 << new_transferred_target_area[u] << std::endl;
30579 oomph_info <<
"Time for loop over integration points in new mesh: "
30580 << TimingHelpers::timer()-t0_loop_int_pts
30611 const double t_sub_total_transfer_target_areas =
30612 TimingHelpers::timer()-t_start_transfer_target_areas;
30614 if (Print_timings_level_adaptation>2)
30617 const unsigned n_element = this->nelement();
30619 const unsigned n_element_background = tmp_new_mesh_pt->nelement();
30621 oomph_info <<
"CPU for transfer of target areas "
30622 <<
"[n_ele_old_mesh="
30623 << n_element <<
", n_ele_background_mesh="
30624 << n_element_background<<
"] (iter "<< iter <<
"): "
30625 << t_sub_total_transfer_target_areas<< std::endl;
30629 t_total_transfer_target_areas+=t_sub_total_transfer_target_areas;
30639 const double t_start_limit_target_areas = TimingHelpers::timer();
30643 #ifdef OOMPH_HAS_MPI
30644 unsigned n_ele_need_refinement_iter = 0;
30656 const unsigned nel_new=tmp_new_mesh_pt->nelement();
30657 Vector<double> new_target_area(nel_new);
30658 for (
unsigned e=0;e<nel_new;e++)
30661 FiniteElement* f_ele_pt = tmp_new_mesh_pt->finite_element_pt(e);
30664 const double new_area=new_transferred_target_area[e];
30667 std::ostringstream error_stream;
30668 error_stream <<
"This shouldn't happen! Element whose centroid is at "
30669 << (f_ele_pt->node_pt(0)->x(0)+
30670 f_ele_pt->node_pt(1)->x(0)+
30671 f_ele_pt->node_pt(2)->x(0))/3.0 <<
" "
30672 << (f_ele_pt->node_pt(0)->x(1)+
30673 f_ele_pt->node_pt(1)->x(1)+
30674 f_ele_pt->node_pt(2)->x(1))/3.0 <<
" "
30675 <<
" has no target area assigned\n";
30676 throw OomphLibError(error_stream.str(),
30677 OOMPH_CURRENT_FUNCTION,
30678 OOMPH_EXCEPTION_LOCATION);
30686 new_target_area[e]=new_area;
30687 if (new_target_area[e]<f_ele_pt->size()/3.0)
30689 new_target_area[e]=f_ele_pt->size()/3.0;
30709 #ifdef OOMPH_HAS_MPI
30711 n_ele_need_refinement_iter++;
30722 const double t_sub_total_limit_target_areas =
30723 TimingHelpers::timer() - t_start_limit_target_areas;
30726 t_total_limit_target_areas+=t_sub_total_limit_target_areas;
30728 if (Print_timings_level_adaptation>2)
30731 const unsigned n_element = this->nelement();
30733 const unsigned n_element_background = tmp_new_mesh_pt->nelement();
30735 oomph_info <<
"CPU for limiting target areas "
30736 <<
"[n_ele_old_mesh="
30737 << n_element <<
", n_ele_background_mesh="
30738 << n_element_background<<
"] (iter "<< iter <<
"): "
30739 << t_sub_total_limit_target_areas<< std::endl;
30745 <<
"All area adjustments accommodated by max. permitted area"
30746 <<
" reduction \n";
30751 <<
"NOT all area adjustments accommodated by max. "
30752 <<
"permitted area reduction \n";
30765 const double t_start_create_new_adapted_mesh =
30766 TimingHelpers::timer();
30769 if (solid_mesh_pt!=0)
30773 tmp_new_triangulateio,
30774 this->Time_stepper_pt,
30775 this->Use_attributes,
30776 this->Allow_automatic_creation_of_vertices_on_boundaries,
30777 this->communicator_pt());
30784 tmp_new_triangulateio,
30785 this->Time_stepper_pt,
30786 this->Use_attributes,
30787 this->Allow_automatic_creation_of_vertices_on_boundaries,
30788 this->communicator_pt());
30792 const double t_sub_total_create_new_adapted_mesh =
30793 TimingHelpers::timer() - t_start_create_new_adapted_mesh;
30796 t_total_create_new_adapted_mesh+=t_sub_total_create_new_adapted_mesh;
30798 if (Print_timings_level_adaptation>2)
30801 const unsigned n_element_new_adapted_mesh = new_mesh_pt->nelement();
30803 oomph_info <<
"CPU for creation of new adapted mesh "
30804 << t_sub_total_create_new_adapted_mesh
30805 <<
"[nele="<<n_element_new_adapted_mesh
30806 <<
"] (iter "<< iter <<
"): "
30807 << t_sub_total_create_new_adapted_mesh << std::endl;
30810 #ifdef OOMPH_HAS_MPI
30821 if (this->nshared_boundary_overlaps_internal_boundary() > 0)
30826 this->shared_boundary_overlaps_internal_boundary();
30831 this->shared_boundaries_ids();
30836 fill_boundary_elements_and_nodes_for_internal_boundaries();
30841 #endif // #ifdef OOMPH_HAS_MPI
30848 new_mesh_pt->boundary_geom_object_pt() =
30849 this->boundary_geom_object_pt();
30853 new_mesh_pt->boundary_coordinate_limits() =
30854 this->boundary_coordinate_limits();
30856 const double t_start_third_stage_segments_connectivity =
30857 TimingHelpers::timer();
30859 for (
unsigned b=0;b<n_boundary;b++)
30868 #ifdef OOMPH_HAS_MPI
30869 if (this->is_mesh_distributed())
30874 identify_boundary_segments_and_assign_initial_zeta_values(b,
this);
30883 if(new_mesh_pt->boundary_geom_object_pt(b)!=0)
30885 new_mesh_pt->template setup_boundary_coordinates<ELEMENT>(b);
30890 t_total_third_stage_segments_connectivity+=
30891 TimingHelpers::timer() - t_start_third_stage_segments_connectivity;
30893 const double t_start_snap_nodes_new_mesh=TimingHelpers::timer();
30897 for(
unsigned b=0;b<n_boundary;b++)
30899 this->snap_nodes_onto_boundary(new_mesh_pt,b);
30902 const double t_sub_total_snap_nodes_new_mesh =
30903 TimingHelpers::timer() - t_start_snap_nodes_new_mesh;
30906 t_total_snap_nodes+=t_sub_total_snap_nodes_new_mesh;
30908 if (Print_timings_level_adaptation>2)
30910 oomph_info <<
"CPU for snapping nodes onto boundaries (new mesh) "
30911 <<
"(iter "<<iter<<
"): "
30912 << t_sub_total_snap_nodes_new_mesh<< std::endl;
30916 if (Mesh_update_fct_pt!=0)
30918 Mesh_update_fct_pt(new_mesh_pt);
30925 if(
dynamic_cast<GeneralisedTimeStepper*
>(this->Time_stepper_pt))
30927 new_mesh_pt->set_nodal_and_elemental_time_stepper(
30928 this->Time_stepper_pt,
false);
30934 delete tmp_new_mesh_pt;
30936 #ifdef OOMPH_HAS_MPI
30940 if (n_ele_need_refinement_iter == n_ele_need_refinement)
30944 n_ele_need_refinement = n_ele_need_refinement_iter;
30945 #endif // #ifdef OOMPH_HAS_MPI
30954 #ifdef OOMPH_HAS_MPI
30955 if (this->is_mesh_distributed())
30958 const double t_start_wait_other_processors = TimingHelpers::timer();
30965 unsigned this_processor_requires_another_iteration = 1;
30968 if (done){this_processor_requires_another_iteration = 0;}
30969 int nproc_not_done = this_processor_requires_another_iteration;
30971 OomphCommunicator* comm_pt = this->communicator_pt();
30974 MPI_Allreduce(&this_processor_requires_another_iteration,
30976 MPI_UNSIGNED,MPI_SUM,comm_pt->mpi_comm());
30978 if (nproc_not_done > 0)
30980 oomph_info <<
"At least one processors requires further refinement. "
30981 <<
"Go for another iteration." << std::endl;
30987 const double t_sub_total_wait_other_processors =
30988 TimingHelpers::timer() - t_start_wait_other_processors;
30992 t_total_wait_other_processors+=t_sub_total_wait_other_processors;
30994 if (Print_timings_level_adaptation>2)
30996 oomph_info <<
"CPU for waiting other processors "
30997 <<
"(iter "<<iter<<
"): "
30998 << t_sub_total_wait_other_processors
31010 oomph_info <<
"Going for another iteration. Current iteration ("
31011 << iter <<
")" << std::endl;
31014 tmp_new_mesh_pt=new_mesh_pt;
31015 tmp_new_triangulateio=new_mesh_pt->triangulateio_representation();
31022 delete mesh_geom_obj_pt;
31024 oomph_info <<
"CPU for iterative generation of new mesh (TOTAL): "
31025 << TimingHelpers::timer()-t_iter
31028 if (Print_timings_level_adaptation>1)
31030 oomph_info <<
"-- CPU for creating new adapted meshes (TOTAL): "
31031 << t_total_create_new_adapted_mesh << std::endl;
31033 oomph_info <<
"-- CPU for limiting target areas (TOTAL): "
31034 << t_total_limit_target_areas << std::endl;
31036 oomph_info <<
"-- CPU for transferring target areas (TOTAL): "
31037 << t_total_transfer_target_areas << std::endl;
31039 oomph_info <<
"-- CPU for waiting other processors (TOTAL): "
31040 << t_total_wait_other_processors << std::endl;
31052 if (!Disable_projection)
31055 double tt_start_projection=TimingHelpers::timer();
31058 if (Print_timings_projection)
31061 Multi_domain_functions::Doc_timings=
true;
31062 Multi_domain_functions::Doc_stats=
true;
31063 Multi_domain_functions::Doc_full_stats=
true;
31066 double t_proj=TimingHelpers::timer();
31067 oomph_info <<
"About to begin projection.\n";
31071 ProjectionProblem<ELEMENT>* project_problem_pt=
31072 new ProjectionProblem<ELEMENT>;
31076 #ifdef OOMPH_HAS_MPI
31077 if (this->is_mesh_distributed())
31085 Time* backed_up_time_pt = this->Time_stepper_pt->time_pt();
31088 project_problem_pt->enable_problem_distributed();
31092 project_problem_pt->add_time_stepper_pt(this->Time_stepper_pt);
31095 project_problem_pt->mesh_pt()=new_mesh_pt;
31100 if(!this->use_iterative_solver_for_projection())
31102 project_problem_pt->disable_use_iterative_solver_for_projection();
31106 project_problem_pt->project(
this);
31109 this->Time_stepper_pt->time_pt() = backed_up_time_pt;
31117 #endif // #ifdef OOMPH_HAS_MPI
31120 project_problem_pt->mesh_pt()=new_mesh_pt;
31126 if(!this->use_iterative_solver_for_projection())
31128 project_problem_pt->disable_use_iterative_solver_for_projection();
31132 project_problem_pt->project(
this);
31136 if (Print_timings_projection)
31139 Multi_domain_functions::Doc_timings=
false;
31140 Multi_domain_functions::Doc_stats=
false;
31141 Multi_domain_functions::Doc_full_stats=
false;
31145 const double tt_projection = TimingHelpers::timer()-tt_start_projection;
31147 if (Print_timings_level_adaptation>1)
31150 const unsigned n_element = this->nelement();
31152 const unsigned n_element_new = new_mesh_pt->nelement();
31153 oomph_info <<
"CPU for projection (in mesh adaptation) "
31154 <<
"[n_ele_old_mesh="<< n_element
31155 <<
", n_ele_new_mesh="<< n_element_new<<
"]: "
31156 << tt_projection << std::endl;
31161 #ifdef OOMPH_HAS_MPI
31162 if (this->is_mesh_distributed())
31166 unsigned n_this_element_new = n_element_new;
31167 unsigned n_max_element_new_global = 0;
31169 MPI_Reduce(&n_this_element_new, &n_max_element_new_global,
31170 1, MPI_UNSIGNED, MPI_MAX, 0,
31171 this->communicator_pt()->mpi_comm());
31174 double tt_this_projection = tt_projection;
31175 double tt_global_min_projection = 0.0;
31176 double tt_global_max_projection = 0.0;
31179 MPI_Reduce(&tt_this_projection, &tt_global_min_projection,
31180 1, MPI_DOUBLE, MPI_MIN, 0,
31181 this->communicator_pt()->mpi_comm());
31182 MPI_Reduce(&tt_this_projection, &tt_global_max_projection,
31183 1, MPI_DOUBLE, MPI_MAX, 0,
31184 this->communicator_pt()->mpi_comm());
31186 if (this->communicator_pt()->my_rank() == 0)
31188 oomph_info <<
"CPU for projection global (MIN): "
31189 << tt_global_min_projection << std::endl;
31190 oomph_info <<
"CPU for projection global (MAX) "
31191 <<
"[n_max_ele_new_global="
31192 << n_max_element_new_global<<
"]: "
31193 << tt_global_max_projection << std::endl;
31195 std::cerr <<
"CPU for projection global (MIN): "
31196 << tt_global_min_projection << std::endl;
31197 std::cerr <<
"CPU for projection global (MAX): "
31198 <<
"[n_max_ele_new_global="
31199 << n_max_element_new_global<<
"]: "
31200 << tt_global_max_projection << std::endl;
31205 #endif // #ifdef OOMPH_HAS_MPI
31212 oomph_info <<
"CPU for projection of solution onto new mesh: "
31213 << TimingHelpers::timer()-t_proj
31217 delete project_problem_pt;
31222 oomph_info <<
"Projection disabled! The new mesh will contain zeros"
31230 double t_rest=TimingHelpers::timer();
31233 unsigned nnod=nnode();
31234 for(
unsigned j=nnod;j>0;j--)
31236 delete Node_pt[j-1];
31239 unsigned nel=nelement();
31240 for(
unsigned e=nel;e>0;e--)
31242 delete Element_pt[e-1];
31243 Element_pt[e-1] = 0;
31248 nnod=new_mesh_pt->nnode();
31249 Node_pt.resize(nnod);
31250 nel=new_mesh_pt->nelement();
31251 Element_pt.resize(nel);
31252 for(
unsigned j=0;j<nnod;j++)
31254 Node_pt[j] = new_mesh_pt->node_pt(j);
31256 for(
unsigned e=0;e<nel;e++)
31258 Element_pt[e] = new_mesh_pt->element_pt(e);
31263 unsigned nbound = 0;
31265 #ifdef OOMPH_HAS_MPI
31269 if (this->is_mesh_distributed())
31274 nbound = new_mesh_pt->nboundary();
31283 nbound = n_boundary;
31286 Boundary_element_pt.resize(nbound);
31287 Face_index_at_boundary.resize(nbound);
31288 Boundary_node_pt.resize(nbound);
31289 for (
unsigned b=0;b<nbound;b++)
31291 unsigned nel=new_mesh_pt->nboundary_element(b);
31292 Boundary_element_pt[b].resize(nel);
31293 Face_index_at_boundary[b].resize(nel);
31294 for (
unsigned e=0;e<nel;e++)
31296 Boundary_element_pt[b][e]=new_mesh_pt->boundary_element_pt(b,e);
31297 Face_index_at_boundary[b][e]=new_mesh_pt->face_index_at_boundary(b,e);
31299 unsigned nnod=new_mesh_pt->nboundary_node(b);
31300 Boundary_node_pt[b].resize(nnod);
31301 for (
unsigned j=0;j<nnod;j++)
31303 Boundary_node_pt[b][j]=new_mesh_pt->boundary_node_pt(b,j);
31308 unsigned n_region = new_mesh_pt->nregion();
31313 this->Region_attribute.resize(n_region);
31314 for(
unsigned r=0;r<n_region;r++)
31316 this->Region_attribute[r] = new_mesh_pt->region_attribute(r);
31318 unsigned r_id =
static_cast<unsigned>(this->Region_attribute[r]);
31320 unsigned n_region_element = new_mesh_pt->nregion_element(r_id);
31321 this->Region_element_pt[r_id].resize(n_region_element);
31322 for(
unsigned e=0;e<n_region_element;e++)
31324 this->Region_element_pt[r_id][e] =
31325 new_mesh_pt->region_element_pt(r_id,e);
31330 this->Boundary_region_element_pt.resize(nbound);
31331 this->Face_index_region_at_boundary.resize(nbound);
31334 for(
unsigned b=0;b<nbound;++b)
31336 for (
unsigned rr = 0 ; rr < n_region; rr++)
31339 unsigned r =
static_cast<unsigned>(this->Region_attribute[rr]);
31341 unsigned n_boundary_el_in_region =
31342 new_mesh_pt->nboundary_element_in_region(b,r);
31344 if(n_boundary_el_in_region > 0)
31347 this->Boundary_region_element_pt[b][r].
31348 resize(n_boundary_el_in_region);
31349 this->Face_index_region_at_boundary[b][r].
31350 resize(n_boundary_el_in_region);
31353 for(
unsigned e=0;e<n_boundary_el_in_region;++e)
31355 this->Boundary_region_element_pt[b][r][e]
31356 = new_mesh_pt->boundary_element_in_region_pt(b,r,e);
31357 this->Face_index_region_at_boundary[b][r][e]
31358 = new_mesh_pt->face_index_at_boundary_in_region(b,r,e);
31371 #ifdef OOMPH_HAS_MPI
31372 if (this->is_mesh_distributed())
31377 if (this->is_mesh_distributed())
31379 this->Halo_node_pt.clear();
31380 this->Root_halo_element_pt.clear();
31382 this->Haloed_node_pt.clear();
31383 this->Root_haloed_element_pt.clear();
31385 this->External_halo_node_pt.clear();
31386 this->External_halo_element_pt.clear();
31388 this->External_haloed_node_pt.clear();
31389 this->External_haloed_element_pt.clear();
31394 this->reset_shared_boundary_elements_and_nodes();
31404 Vector<unsigned> my_rank_shared_boundaries_ids;
31405 this->shared_boundaries_in_this_processor(my_rank_shared_boundaries_ids);
31408 const unsigned nmy_rank_shd_bnd = my_rank_shared_boundaries_ids.size();
31411 for (
unsigned i = 0; i < nmy_rank_shd_bnd; i++)
31414 const unsigned shd_bnd_id = my_rank_shared_boundaries_ids[i];
31417 this->Boundary_element_pt[shd_bnd_id].clear();
31421 const unsigned tmp_nnodes =
31422 this->nshared_boundary_node(shd_bnd_id);
31423 for (
unsigned n = 0; n < tmp_nnodes; n++)
31425 Node* tmp_node_pt = this->boundary_node_pt(shd_bnd_id, n);
31426 tmp_node_pt->remove_from_boundary(shd_bnd_id);
31432 this->set_nboundary(n_boundary);
31436 this->sort_nodes_on_shared_boundaries();
31439 this->reset_halo_haloed_scheme();
31443 for (
unsigned b = 0; b < n_boundary; b++)
31445 if (this->boundary_geom_object_pt(b)!=0)
31447 const unsigned nsegments = new_mesh_pt->nboundary_segment(b);
31448 this->set_nboundary_segment_node(b, nsegments);
31453 resume_boundary_connections(resume_initial_connection_polyline_pt,
31454 resume_final_connection_polyline_pt);
31458 #endif // #ifdef OOMPH_HAS_MPI
31465 this->snap_nodes_onto_geometric_objects();
31471 TriangleHelper::clear_triangulateio(this->Triangulateio);
31473 this->Triangulateio=
31474 TriangleHelper::deep_copy_of_triangulateio_representation(
31475 new_mesh_pt->triangulateio_representation(),quiet);
31478 new_mesh_pt->flush_element_and_node_storage();
31481 delete new_mesh_pt;
31484 if (Print_timings_level_adaptation>2)
31488 oomph_info <<
"CPU for segments connectivity (first stage) [sec]: "
31489 << t_total_first_stage_segments_connectivity << std::endl;
31490 oomph_info <<
"CPU for segments connectivity (second stage) [sec]: "
31491 << t_total_second_stage_segments_connectivity << std::endl;
31492 oomph_info <<
"CPU for segments connectivity (third stage) [sec]: "
31493 << t_total_third_stage_segments_connectivity << std::endl;
31496 if (Print_timings_level_adaptation>1)
31498 const double t_total_segments_connectivity =
31499 t_total_first_stage_segments_connectivity +
31500 t_total_second_stage_segments_connectivity +
31501 t_total_third_stage_segments_connectivity;
31503 oomph_info <<
"CPU for segments connectivity (TOTAL) [sec]: "
31504 << t_total_segments_connectivity << std::endl;
31506 if (Print_timings_level_adaptation>2)
31509 oomph_info <<
"CPU for snapping nodes onto boundaries "
31511 << t_total_snap_nodes << std::endl;
31514 t_total_snap_nodes+=t_total_snap_nodes_bg_mesh;
31515 oomph_info <<
"CPU for snapping nodes onto boundaries (TOTAL): "
31516 << t_total_snap_nodes << std::endl;
31519 double max_area=0.0;
31520 double min_area=0.0;
31522 this->max_and_min_element_size(max_area, min_area);
31523 oomph_info <<
"Max/min element size in adapted mesh: "
31525 << min_area << std::endl;
31527 oomph_info <<
"CPU time for final bits [sec]: "
31528 << TimingHelpers::timer()-t_rest
31533 oomph_info <<
"Not enough benefit in adaptation.\n";
31538 double CPU_for_adaptation = TimingHelpers::timer()-t_start_overall;
31539 oomph_info <<
"CPU time for adaptation [sec]: "
31540 << CPU_for_adaptation << std::endl;
31545 #ifdef OOMPH_HAS_MPI
31546 if (this->is_mesh_distributed())
31549 OomphCommunicator* comm_pt = this->communicator_pt();
31551 const unsigned n_proc = comm_pt->nproc();
31552 if (Print_timings_level_adaptation>1 && n_proc>1)
31554 double global_min_CPU_for_adaptation = 0.0;
31555 double global_max_CPU_for_adaptation = 0.0;
31556 double global_average_CPU_for_adaptation = 0.0;
31559 MPI_Reduce(&CPU_for_adaptation, &global_min_CPU_for_adaptation,
31560 1, MPI_DOUBLE, MPI_MIN, 0, comm_pt->mpi_comm());
31561 MPI_Reduce(&CPU_for_adaptation, &global_max_CPU_for_adaptation,
31562 1, MPI_DOUBLE, MPI_MAX, 0, comm_pt->mpi_comm());
31563 MPI_Reduce(&CPU_for_adaptation, &global_average_CPU_for_adaptation,
31564 1, MPI_DOUBLE, MPI_SUM, 0, comm_pt->mpi_comm());
31567 const unsigned my_rank = comm_pt->my_rank();
31570 oomph_info <<
"CPU for adaptation (MIN): "
31571 << global_min_CPU_for_adaptation << std::endl;
31572 oomph_info <<
"CPU for adaptation (MAX): "
31573 << global_max_CPU_for_adaptation << std::endl;
31574 oomph_info <<
"CPU for adaptation (AVERAGE): "
31575 << global_average_CPU_for_adaptation/n_proc << std::endl;
31586 #endif // #ifdef OOMPH_HAS_MPI
31597 template<
class ELEMENT>
31602 Boundary_connections_pt.clear();
31609 std::set<unsigned> boundary_id_with_connections;
31616 const unsigned n_outer_boundaries = this->Outer_boundary_pt.size();
31619 for (
unsigned i = 0; i < n_outer_boundaries; i++)
31622 TriangleMeshPolygon* tmp_polygon_pt = this->Outer_boundary_pt[i];
31625 const unsigned n_polyline = tmp_polygon_pt->npolyline();
31627 for (
unsigned p = 0; p < n_polyline; p++)
31630 TriangleMeshPolyLine* tmp_polyline_pt =
31631 tmp_polygon_pt->polyline_pt(p);
31634 if (tmp_polyline_pt->is_initial_vertex_connected())
31637 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
31641 boundary_id_with_connections.insert(bnd_id);
31644 const unsigned dst_bnd_id =
31645 tmp_polyline_pt->initial_vertex_connected_bnd_id();
31649 boundary_id_with_connections.insert(dst_bnd_id);
31654 if (tmp_polyline_pt->is_final_vertex_connected())
31657 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
31661 boundary_id_with_connections.insert(bnd_id);
31664 const unsigned dst_bnd_id =
31665 tmp_polyline_pt->final_vertex_connected_bnd_id();
31669 boundary_id_with_connections.insert(dst_bnd_id);
31682 const unsigned n_internal_boundaries = this->Internal_polygon_pt.size();
31685 for (
unsigned i = 0; i < n_internal_boundaries; i++)
31688 TriangleMeshPolygon* tmp_polygon_pt = this->Internal_polygon_pt[i];
31691 const unsigned n_polyline = tmp_polygon_pt->npolyline();
31693 for (
unsigned p = 0; p < n_polyline; p++)
31696 TriangleMeshPolyLine* tmp_polyline_pt =
31697 tmp_polygon_pt->polyline_pt(p);
31700 if (tmp_polyline_pt->is_initial_vertex_connected())
31703 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
31707 boundary_id_with_connections.insert(bnd_id);
31710 const unsigned dst_bnd_id =
31711 tmp_polyline_pt->initial_vertex_connected_bnd_id();
31715 boundary_id_with_connections.insert(dst_bnd_id);
31720 if (tmp_polyline_pt->is_final_vertex_connected())
31723 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
31727 boundary_id_with_connections.insert(bnd_id);
31730 const unsigned dst_bnd_id =
31731 tmp_polyline_pt->final_vertex_connected_bnd_id();
31735 boundary_id_with_connections.insert(dst_bnd_id);
31748 const unsigned n_open_boundaries = this->Internal_open_curve_pt.size();
31751 for (
unsigned i = 0; i < n_open_boundaries; i++)
31754 TriangleMeshOpenCurve* tmp_open_curve_pt =
31755 this->Internal_open_curve_pt[i];
31759 const unsigned n_curve_section = tmp_open_curve_pt->ncurve_section();
31762 for (
unsigned p = 0; p < n_curve_section; p++)
31766 TriangleMeshPolyLine* tmp_polyline_pt =
31767 tmp_open_curve_pt->polyline_pt(p);
31770 if (tmp_polyline_pt->is_initial_vertex_connected())
31773 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
31777 boundary_id_with_connections.insert(bnd_id);
31780 const unsigned dst_bnd_id =
31781 tmp_polyline_pt->initial_vertex_connected_bnd_id();
31785 boundary_id_with_connections.insert(dst_bnd_id);
31790 if (tmp_polyline_pt->is_final_vertex_connected())
31793 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
31797 boundary_id_with_connections.insert(bnd_id);
31800 const unsigned dst_bnd_id =
31801 tmp_polyline_pt->final_vertex_connected_bnd_id();
31805 boundary_id_with_connections.insert(dst_bnd_id);
31813 #ifdef OOMPH_HAS_MPI
31820 if (this->is_mesh_distributed())
31823 const unsigned my_rank = this->communicator_pt()->my_rank();
31826 const unsigned n_shared_curves =
31827 this->nshared_boundary_curves(my_rank);
31830 for (
unsigned i = 0; i < n_shared_curves; i ++)
31834 const unsigned n_polyline =
31835 this->nshared_boundary_polyline(my_rank, i);
31839 for (
unsigned p = 0; p < n_polyline; p++)
31842 TriangleMeshPolyLine* tmp_polyline_pt =
31843 this->shared_boundary_polyline_pt(my_rank, i, p);
31846 if (tmp_polyline_pt->is_initial_vertex_connected())
31849 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
31853 boundary_id_with_connections.insert(bnd_id);
31856 const unsigned dst_bnd_id =
31857 tmp_polyline_pt->initial_vertex_connected_bnd_id();
31861 boundary_id_with_connections.insert(dst_bnd_id);
31866 if (tmp_polyline_pt->is_final_vertex_connected())
31869 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
31873 boundary_id_with_connections.insert(bnd_id);
31876 const unsigned dst_bnd_id =
31877 tmp_polyline_pt->final_vertex_connected_bnd_id();
31881 boundary_id_with_connections.insert(dst_bnd_id);
31891 #endif // #ifdef OOMPH_HAS_MPI
31899 std::map<unsigned, Vector<Vector<Node*> > > bnd_sorted_segment_node_pt;
31902 for (std::set<unsigned>::iterator it =
31903 boundary_id_with_connections.begin();
31904 it != boundary_id_with_connections.end(); it++)
31907 const unsigned bnd_id = (*it);
31908 #ifdef OOMPH_HAS_MPI
31910 if (this->is_mesh_distributed())
31913 const unsigned init_shd_bnd_id = this->initial_shared_boundary_id();
31915 if (bnd_id >= init_shd_bnd_id)
31920 Vector<Vector<Node*> > tmp_shared_nodes_pt;
31923 get_shared_boundary_segment_nodes_helper(bnd_id,
31924 tmp_shared_nodes_pt);
31927 bnd_sorted_segment_node_pt[bnd_id] = tmp_shared_nodes_pt;
31935 Vector<Vector<Node*> > tmp_boundary_nodes_pt;
31938 get_boundary_segment_nodes_helper(bnd_id,
31939 tmp_boundary_nodes_pt);
31942 bnd_sorted_segment_node_pt[bnd_id] = tmp_boundary_nodes_pt;
31948 #endif // #ifdef OOMPH_HAS_MPI
31953 Vector<Vector<Node*> > tmp_boundary_nodes_pt;
31956 get_boundary_segment_nodes_helper(bnd_id,
31957 tmp_boundary_nodes_pt);
31960 bnd_sorted_segment_node_pt[bnd_id] = tmp_boundary_nodes_pt;
31974 for (
unsigned i = 0; i < n_outer_boundaries; i++)
31977 TriangleMeshPolygon* tmp_polygon_pt = this->Outer_boundary_pt[i];
31980 const unsigned n_polyline = tmp_polygon_pt->npolyline();
31982 for (
unsigned p = 0; p < n_polyline; p++)
31985 TriangleMeshPolyLine* tmp_polyline_pt =
31986 tmp_polygon_pt->polyline_pt(p);
31989 if (tmp_polyline_pt->is_initial_vertex_connected())
31992 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
31995 const unsigned dst_bnd_id =
31996 tmp_polyline_pt->initial_vertex_connected_bnd_id();
31999 const unsigned dst_chunk =
32000 tmp_polyline_pt->initial_vertex_connected_n_chunk();
32003 Vector<Vector<Node*> > src_bnd_node_pt =
32004 bnd_sorted_segment_node_pt[bnd_id];
32007 Vector<Vector<Node*> > dst_bnd_node_pt =
32008 bnd_sorted_segment_node_pt[dst_bnd_id];
32012 add_non_delete_vertices_from_boundary_helper(
32013 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32018 if (tmp_polyline_pt->is_final_vertex_connected())
32021 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
32024 const unsigned dst_bnd_id =
32025 tmp_polyline_pt->final_vertex_connected_bnd_id();
32028 const unsigned dst_chunk =
32029 tmp_polyline_pt->final_vertex_connected_n_chunk();
32032 Vector<Vector<Node*> > src_bnd_node_pt =
32033 bnd_sorted_segment_node_pt[bnd_id];
32036 Vector<Vector<Node*> > dst_bnd_node_pt =
32037 bnd_sorted_segment_node_pt[dst_bnd_id];
32041 add_non_delete_vertices_from_boundary_helper(
32042 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32054 for (
unsigned i = 0; i < n_internal_boundaries; i++)
32057 TriangleMeshPolygon* tmp_polygon_pt = this->Internal_polygon_pt[i];
32060 const unsigned n_polyline = tmp_polygon_pt->npolyline();
32062 for (
unsigned p = 0; p < n_polyline; p++)
32065 TriangleMeshPolyLine* tmp_polyline_pt =
32066 tmp_polygon_pt->polyline_pt(p);
32069 if (tmp_polyline_pt->is_initial_vertex_connected())
32072 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
32075 const unsigned dst_bnd_id =
32076 tmp_polyline_pt->initial_vertex_connected_bnd_id();
32079 const unsigned dst_chunk =
32080 tmp_polyline_pt->initial_vertex_connected_n_chunk();
32083 Vector<Vector<Node*> > src_bnd_node_pt =
32084 bnd_sorted_segment_node_pt[bnd_id];
32087 Vector<Vector<Node*> > dst_bnd_node_pt =
32088 bnd_sorted_segment_node_pt[dst_bnd_id];
32092 add_non_delete_vertices_from_boundary_helper(
32093 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32098 if (tmp_polyline_pt->is_final_vertex_connected())
32101 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
32104 const unsigned dst_bnd_id =
32105 tmp_polyline_pt->final_vertex_connected_bnd_id();
32108 const unsigned dst_chunk =
32109 tmp_polyline_pt->final_vertex_connected_n_chunk();
32112 Vector<Vector<Node*> > src_bnd_node_pt =
32113 bnd_sorted_segment_node_pt[bnd_id];
32116 Vector<Vector<Node*> > dst_bnd_node_pt =
32117 bnd_sorted_segment_node_pt[dst_bnd_id];
32121 add_non_delete_vertices_from_boundary_helper(
32122 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32134 for (
unsigned i = 0; i < n_open_boundaries; i++)
32137 TriangleMeshOpenCurve* tmp_open_curve_pt =
32138 this->Internal_open_curve_pt[i];
32142 const unsigned n_curve_section = tmp_open_curve_pt->ncurve_section();
32145 for (
unsigned p = 0; p < n_curve_section; p++)
32149 TriangleMeshPolyLine* tmp_polyline_pt =
32150 tmp_open_curve_pt->polyline_pt(p);
32153 if (tmp_polyline_pt->is_initial_vertex_connected())
32156 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
32159 const unsigned dst_bnd_id =
32160 tmp_polyline_pt->initial_vertex_connected_bnd_id();
32163 const unsigned dst_chunk =
32164 tmp_polyline_pt->initial_vertex_connected_n_chunk();
32167 Vector<Vector<Node*> > src_bnd_node_pt =
32168 bnd_sorted_segment_node_pt[bnd_id];
32171 Vector<Vector<Node*> > dst_bnd_node_pt =
32172 bnd_sorted_segment_node_pt[dst_bnd_id];
32176 add_non_delete_vertices_from_boundary_helper(
32177 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32182 if (tmp_polyline_pt->is_final_vertex_connected())
32185 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
32188 const unsigned dst_bnd_id =
32189 tmp_polyline_pt->final_vertex_connected_bnd_id();
32192 const unsigned dst_chunk =
32193 tmp_polyline_pt->final_vertex_connected_n_chunk();
32196 Vector<Vector<Node*> > src_bnd_node_pt =
32197 bnd_sorted_segment_node_pt[bnd_id];
32200 Vector<Vector<Node*> > dst_bnd_node_pt =
32201 bnd_sorted_segment_node_pt[dst_bnd_id];
32205 add_non_delete_vertices_from_boundary_helper(
32206 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32214 #ifdef OOMPH_HAS_MPI
32221 if (this->is_mesh_distributed())
32224 const unsigned my_rank = this->communicator_pt()->my_rank();
32227 const unsigned n_shared_curves =
32228 this->nshared_boundary_curves(my_rank);
32231 for (
unsigned i = 0; i < n_shared_curves; i ++)
32235 const unsigned n_polyline =
32236 this->nshared_boundary_polyline(my_rank, i);
32240 for (
unsigned p = 0; p < n_polyline; p++)
32243 TriangleMeshPolyLine* tmp_polyline_pt =
32244 this->shared_boundary_polyline_pt(my_rank, i, p);
32247 if (tmp_polyline_pt->is_initial_vertex_connected())
32250 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
32253 const unsigned dst_bnd_id =
32254 tmp_polyline_pt->initial_vertex_connected_bnd_id();
32257 const unsigned dst_chunk =
32258 tmp_polyline_pt->initial_vertex_connected_n_chunk();
32261 Vector<Vector<Node*> > src_bnd_node_pt =
32262 bnd_sorted_segment_node_pt[bnd_id];
32265 Vector<Vector<Node*> > dst_bnd_node_pt =
32266 bnd_sorted_segment_node_pt[dst_bnd_id];
32270 add_non_delete_vertices_from_boundary_helper(
32271 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32276 if (tmp_polyline_pt->is_final_vertex_connected())
32279 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
32282 const unsigned dst_bnd_id =
32283 tmp_polyline_pt->final_vertex_connected_bnd_id();
32286 const unsigned dst_chunk =
32287 tmp_polyline_pt->final_vertex_connected_n_chunk();
32290 Vector<Vector<Node*> > src_bnd_node_pt =
32291 bnd_sorted_segment_node_pt[bnd_id];
32294 Vector<Vector<Node*> > dst_bnd_node_pt =
32295 bnd_sorted_segment_node_pt[dst_bnd_id];
32299 add_non_delete_vertices_from_boundary_helper(
32300 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32310 #endif // #ifdef OOMPH_HAS_MPI
32319 template<
class ELEMENT>
32322 Vector<Vector<Node*> > src_bound_segment_node_pt,
32323 Vector<Vector<Node*> > dst_bound_segment_node_pt,
32324 const unsigned &dst_bnd_id,
const unsigned &dst_bnd_chunk)
32327 const unsigned n_seg = src_bound_segment_node_pt.size();
32329 for (
unsigned iseg = 0; iseg < n_seg; iseg++)
32332 const unsigned nnode = src_bound_segment_node_pt[iseg].size();
32334 Node* left_node_pt = src_bound_segment_node_pt[iseg][0];
32335 Node* right_node_pt = src_bound_segment_node_pt[iseg][nnode-1];
32338 const unsigned n_dst_seg = dst_bound_segment_node_pt.size();
32340 for (
unsigned jseg = 0; jseg < n_dst_seg; jseg++)
32343 const unsigned n_dst_node = dst_bound_segment_node_pt[jseg].size();
32346 for (
unsigned jnode = 0; jnode < n_dst_node; jnode++)
32350 Node* tmp_node_pt = dst_bound_segment_node_pt[jseg][jnode];
32353 if (tmp_node_pt == left_node_pt)
32356 Vector<double> vertex(2);
32357 vertex[0] = tmp_node_pt->x(0);
32358 vertex[1] = tmp_node_pt->x(1);
32364 Boundary_connections_pt[dst_bnd_id].insert(vertex);
32372 else if (tmp_node_pt == right_node_pt)
32375 Vector<double> vertex(2);
32376 vertex[0] = tmp_node_pt->x(0);
32377 vertex[1] = tmp_node_pt->x(1);
32385 Boundary_connections_pt[dst_bnd_id].insert(vertex);
32400 #ifdef OOMPH_HAS_MPI
32406 template<
class ELEMENT>
32411 const unsigned nproc = this->communicator_pt()->nproc();
32413 const unsigned my_rank = this->communicator_pt()->my_rank();
32416 for (
unsigned jproc = 0; jproc < nproc; jproc++)
32421 const unsigned n_shd_bnd_jproc =
32422 this->nshared_boundaries(my_rank, jproc);
32426 if (jproc != my_rank && n_shd_bnd_jproc > 0)
32430 Vector<unsigned> shd_bnd_id_for_non_deletion;
32434 Vector<unsigned> chunk_for_non_deletion;
32438 Vector<unsigned> number_vertices_non_deletion;
32441 Vector<Vector<Vector<double> > > vertices_for_non_deletion;
32445 Vector<unsigned> shd_bnd_ids =
32446 this->shared_boundaries_ids(my_rank, jproc);
32449 const unsigned n_shd_bnd_jproc = shd_bnd_ids.size();
32451 for (
unsigned ishd_bnd=0;ishd_bnd<n_shd_bnd_jproc;ishd_bnd++)
32454 const unsigned shd_bnd_id = shd_bnd_ids[ishd_bnd];
32456 TriangleMeshPolyLine *shd_polyline_pt =
32457 this->boundary_polyline_pt(shd_bnd_id);
32459 const unsigned chunk = shd_polyline_pt->boundary_chunk();
32462 std::set<Vector<double> > no_delete_vertex;
32465 const bool boundary_receive_connections =
32466 this->boundary_connections(shd_bnd_id, chunk,
32470 const unsigned n_non_delete_vertex = no_delete_vertex.size();
32473 if (boundary_receive_connections && n_non_delete_vertex > 0)
32476 shd_bnd_id_for_non_deletion.push_back(shd_bnd_id);
32478 chunk_for_non_deletion.push_back(chunk);
32480 number_vertices_non_deletion.push_back(n_non_delete_vertex);
32483 Vector<Vector<double> > tmp_vertices;
32486 for (std::set<Vector<double> >::iterator it =
32487 no_delete_vertex.begin();
32488 it != no_delete_vertex.end(); it++)
32491 Vector<double> vertex = (*it);
32492 tmp_vertices.push_back(vertex);
32496 vertices_for_non_deletion.push_back(tmp_vertices);
32510 OomphCommunicator* comm_pt = this->communicator_pt();
32514 MPI_Request request;
32520 const unsigned n_shd_bnd_with_non_delete_vertices =
32521 shd_bnd_id_for_non_deletion.size();
32524 const unsigned size_package = 3;
32526 const unsigned n_unsigned_data_to_send =
32527 n_shd_bnd_with_non_delete_vertices*size_package;
32529 Vector<unsigned> flat_package_unsigned_send(n_unsigned_data_to_send);
32530 Vector<double> flat_package_double_send;
32532 Vector<unsigned> flat_package_unsigned_recv;
32533 Vector<double> flat_package_double_recv;
32537 for (
unsigned i=0;i<n_shd_bnd_with_non_delete_vertices;i++)
32540 flat_package_unsigned_send[j++] =
32541 shd_bnd_id_for_non_deletion[i];
32543 flat_package_unsigned_send[j++] =
32544 chunk_for_non_deletion[i];
32546 flat_package_unsigned_send[j++] =
32547 number_vertices_non_deletion[i];
32549 const unsigned n_vertices_non_deletion =
32550 number_vertices_non_deletion[i];
32553 for (
unsigned h=0;h<n_vertices_non_deletion;h++)
32555 flat_package_double_send.push_back(
32556 vertices_for_non_deletion[i][h][0]);
32557 flat_package_double_send.push_back(
32558 vertices_for_non_deletion[i][h][1]);
32564 int send_proc = jproc;
32565 int recv_proc = jproc;
32566 unsigned send_count_unsigned_values = n_unsigned_data_to_send;
32567 unsigned send_count_double_values = flat_package_double_send.size();
32572 MPI_Isend(&send_count_unsigned_values,1,MPI_UNSIGNED,
32573 send_proc,1,comm_pt->mpi_comm(),&request);
32575 unsigned receive_count_unsigned_values=0;
32576 MPI_Recv(&receive_count_unsigned_values,1,MPI_UNSIGNED,
32577 recv_proc,1,comm_pt->mpi_comm(),&status);
32579 MPI_Wait(&request,MPI_STATUS_IGNORE);
32582 if (send_count_unsigned_values!=0)
32584 MPI_Isend(&flat_package_unsigned_send[0],
32585 send_count_unsigned_values,MPI_UNSIGNED,
32586 send_proc,2,comm_pt->mpi_comm(),&request);
32590 if (receive_count_unsigned_values!=0)
32592 flat_package_unsigned_recv.resize(receive_count_unsigned_values);
32593 MPI_Recv(&flat_package_unsigned_recv[0],
32594 receive_count_unsigned_values,
32595 MPI_UNSIGNED,recv_proc,2,comm_pt->mpi_comm(),&status);
32600 if (send_count_unsigned_values!=0)
32602 MPI_Wait(&request,MPI_STATUS_IGNORE);
32607 MPI_Isend(&send_count_double_values,1,MPI_UNSIGNED,
32608 send_proc,1,comm_pt->mpi_comm(),&request);
32610 unsigned receive_count_double_values=0;
32611 MPI_Recv(&receive_count_double_values,1,MPI_UNSIGNED,
32612 recv_proc,1,comm_pt->mpi_comm(),&status);
32614 MPI_Wait(&request,MPI_STATUS_IGNORE);
32617 if (send_count_double_values!=0)
32619 MPI_Isend(&flat_package_double_send[0],
32620 send_count_double_values,MPI_DOUBLE,
32621 send_proc,2,comm_pt->mpi_comm(),&request);
32625 if (receive_count_double_values!=0)
32627 flat_package_double_recv.resize(receive_count_double_values);
32628 MPI_Recv(&flat_package_double_recv[0],
32629 receive_count_double_values,
32630 MPI_DOUBLE,recv_proc,2,comm_pt->mpi_comm(),&status);
32635 if (send_count_double_values!=0)
32637 MPI_Wait(&request,MPI_STATUS_IGNORE);
32650 Vector<unsigned> recv_shd_bnd_id_for_non_deletion;
32654 Vector<unsigned> recv_chunk_for_non_deletion;
32658 Vector<unsigned> recv_number_vertices_non_deletion;
32661 Vector<Vector<Vector<double> > > recv_vertices_for_non_deletion;
32665 for (
unsigned i=0;i<receive_count_unsigned_values;i+=3)
32668 const unsigned recv_shd_bnd_id =
32669 flat_package_unsigned_recv[i];
32670 recv_shd_bnd_id_for_non_deletion.push_back(recv_shd_bnd_id);
32672 const unsigned recv_chunk =
32673 flat_package_unsigned_recv[i+1];
32674 recv_chunk_for_non_deletion.push_back(recv_chunk);
32676 const unsigned recv_num_vertices =
32677 flat_package_unsigned_recv[i+2];
32678 recv_number_vertices_non_deletion.push_back(recv_num_vertices);
32681 Vector<Vector<double> > temp_recv_vertices;
32683 for (
unsigned h=0;h<recv_num_vertices;h++)
32685 Vector<double> tmp_vertex(2);
32686 tmp_vertex[0] = flat_package_double_recv[j++];
32687 tmp_vertex[1] = flat_package_double_recv[j++];
32689 temp_recv_vertices.push_back(tmp_vertex);
32693 recv_vertices_for_non_deletion.push_back(temp_recv_vertices);
32708 const unsigned n_recv_shd_bnd_id_for_non_deletion =
32709 recv_shd_bnd_id_for_non_deletion.size();
32712 for (
unsigned i=0;i<n_recv_shd_bnd_id_for_non_deletion;i++)
32715 const unsigned shd_bnd_id =
32716 recv_shd_bnd_id_for_non_deletion[i];
32718 unsigned chunk = recv_chunk_for_non_deletion[i];
32725 const unsigned n_vertices =
32726 recv_number_vertices_non_deletion[i];
32728 for (
unsigned h=0;h<n_vertices;h++)
32731 Vector<double> vertex(2);
32732 vertex[0] = recv_vertices_for_non_deletion[i][h][0];
32733 vertex[1] = recv_vertices_for_non_deletion[i][h][1];
32738 Boundary_connections_pt[shd_bnd_id].insert(vertex);
32749 #endif // #ifdef OOMPH_HAS_MPI
32756 template<
class ELEMENT>
32758 Vector<TriangleMeshPolygon *> &tmp_outer_polygons_pt,
32759 Vector<TriangleMeshOpenCurve *> &tmp_open_curves_pt)
32762 Vector<TriangleMeshPolyLine*> dummy_resume_initial_connection_polyline_pt;
32763 Vector<TriangleMeshPolyLine*> dummy_resume_final_connection_polyline_pt;
32766 dummy_resume_initial_connection_polyline_pt.clear();
32767 dummy_resume_final_connection_polyline_pt.clear();
32771 const unsigned init_shd_bnd_id = this->initial_shared_boundary_id();
32789 const unsigned n_outer_boundaries = tmp_outer_polygons_pt.size();
32792 for (
unsigned i = 0; i < n_outer_boundaries; i++)
32795 TriangleMeshPolygon* tmp_polygon_pt = tmp_outer_polygons_pt[i];
32798 const unsigned n_polyline = tmp_polygon_pt->npolyline();
32800 for (
unsigned p = 0; p < n_polyline; p++)
32803 TriangleMeshPolyLine* tmp_polyline_pt =
32804 tmp_polygon_pt->polyline_pt(p);
32807 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
32810 if (bnd_id < init_shd_bnd_id)
32813 restore_polyline_connections_helper(
32815 dummy_resume_initial_connection_polyline_pt,
32816 dummy_resume_final_connection_polyline_pt);
32833 const unsigned n_open_boundaries = tmp_open_curves_pt.size();
32836 for (
unsigned i = 0; i < n_open_boundaries; i++)
32839 TriangleMeshOpenCurve* tmp_open_curve_pt = tmp_open_curves_pt[i];
32843 const unsigned n_curve_section = tmp_open_curve_pt->ncurve_section();
32846 for (
unsigned p = 0; p < n_curve_section; p++)
32850 TriangleMeshPolyLine* tmp_polyline_pt =
32851 tmp_open_curve_pt->polyline_pt(p);
32854 const unsigned bnd_id = tmp_polyline_pt->boundary_id();
32857 if (bnd_id < init_shd_bnd_id)
32860 restore_polyline_connections_helper(
32862 dummy_resume_initial_connection_polyline_pt,
32863 dummy_resume_final_connection_polyline_pt);
32883 template<
class ELEMENT>
32885 Vector<TriangleMeshPolyLine*> &resume_initial_connection_polyline_pt,
32886 Vector<TriangleMeshPolyLine*> &resume_final_connection_polyline_pt)
32889 resume_initial_connection_polyline_pt.clear();
32890 resume_final_connection_polyline_pt.clear();
32901 const unsigned n_outer_boundaries = this->Outer_boundary_pt.size();
32904 for (
unsigned i = 0; i < n_outer_boundaries; i++)
32907 TriangleMeshPolygon* tmp_polygon_pt = this->Outer_boundary_pt[i];
32910 const unsigned n_polyline = tmp_polygon_pt->npolyline();
32912 for (
unsigned p = 0; p < n_polyline; p++)
32915 TriangleMeshPolyLine* tmp_polyline_pt =
32916 tmp_polygon_pt->polyline_pt(p);
32919 restore_polyline_connections_helper(
32921 resume_initial_connection_polyline_pt,
32922 resume_final_connection_polyline_pt);
32933 const unsigned n_internal_boundaries = this->Internal_polygon_pt.size();
32936 for (
unsigned i = 0; i < n_internal_boundaries; i++)
32939 TriangleMeshPolygon* tmp_polygon_pt = this->Internal_polygon_pt[i];
32942 const unsigned n_polyline = tmp_polygon_pt->npolyline();
32944 for (
unsigned p = 0; p < n_polyline; p++)
32947 TriangleMeshPolyLine* tmp_polyline_pt =
32948 tmp_polygon_pt->polyline_pt(p);
32951 restore_polyline_connections_helper(
32953 resume_initial_connection_polyline_pt,
32954 resume_final_connection_polyline_pt);
32965 const unsigned n_open_boundaries = this->Internal_open_curve_pt.size();
32968 for (
unsigned i = 0; i < n_open_boundaries; i++)
32971 TriangleMeshOpenCurve* tmp_open_curve_pt =
32972 this->Internal_open_curve_pt[i];
32976 const unsigned n_curve_section = tmp_open_curve_pt->ncurve_section();
32979 for (
unsigned p = 0; p < n_curve_section; p++)
32983 TriangleMeshPolyLine* tmp_polyline_pt =
32984 tmp_open_curve_pt->polyline_pt(p);
32987 restore_polyline_connections_helper(
32989 resume_initial_connection_polyline_pt,
32990 resume_final_connection_polyline_pt);
33006 template<
class ELEMENT>
33009 TriangleMeshPolyLine* polyline_pt,
33010 Vector<TriangleMeshPolyLine*> &resume_initial_connection_polyline_pt,
33011 Vector<TriangleMeshPolyLine*> &resume_final_connection_polyline_pt)
33018 if (polyline_pt->is_initial_vertex_connected())
33021 TriangleMeshPolyLine *poly_to_connect_pt = 0;
33024 const unsigned dst_bnd_id_initial =
33025 polyline_pt->initial_vertex_connected_bnd_id();
33028 Vector<double> src_vertex_coordinates_initial =
33029 polyline_pt->vertex_coordinate(0);
33033 #ifdef OOMPH_HAS_MPI
33034 if (this->is_mesh_distributed())
33037 const unsigned init_shd_bnd_id =
33038 this->initial_shared_boundary_id();
33040 if (dst_bnd_id_initial >= init_shd_bnd_id)
33043 const unsigned bnd_id = polyline_pt->boundary_id();
33044 std::ostringstream error_message;
33046 <<
"INITIAL VERTEX CONNECTION\n"
33047 <<
"The current original boundary is trying to connect to a\n"
33048 <<
"shared boundary, this is not allowed. In this case the\n"
33049 <<
"shared boundary should be the one that connects with the\n"
33050 <<
"original boundary\n"
33051 <<
"The current original boundary (" << bnd_id <<
") is marked\n"
33052 <<
"to have a connection at the\nINITIAL vertex ("
33053 << src_vertex_coordinates_initial[0] <<
","
33054 << src_vertex_coordinates_initial[1] <<
")\n"
33055 <<
"with the shared boundary ("<< dst_bnd_id_initial <<
")\n"
33056 <<
"This is the list of vertices on the shared destination boundary\n";
33059 TriangleMeshPolyLine *dst_polyline =
33060 this->boundary_polyline_pt(dst_bnd_id_initial);
33062 const unsigned n_vertex_dst_boundary = dst_polyline->nvertex();
33064 for (
unsigned i = 0; i < n_vertex_dst_boundary; i++)
33066 Vector<double> current_vertex = dst_polyline->vertex_coordinate(i);
33069 << current_vertex[0] <<
", " << current_vertex[1] <<
")\n";
33071 throw OomphLibError(
33072 error_message.str(),
33073 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33074 OOMPH_EXCEPTION_LOCATION);
33078 #endif // #ifdef OOMPH_HAS_MPI
33080 #endif // #ifdef PARANOID
33084 bool found_vertex_on_dst_boundary_initial =
false;
33088 unsigned sub_poly_to_connect = 0;
33091 unsigned n_vertex_connection_initial = 0;
33096 bool connecting_to_an_split_boundary =
false;
33100 bool connecting_to_an_overlaped_boundary =
false;
33102 #ifdef OOMPH_HAS_MPI
33103 if (this->is_mesh_distributed())
33108 if (this->boundary_was_splitted(dst_bnd_id_initial))
33110 connecting_to_an_split_boundary =
true;
33119 if (connecting_to_an_split_boundary)
33123 const unsigned n_sub_poly =
33124 this->nboundary_subpolylines(dst_bnd_id_initial);
33128 for (
unsigned ii =0; ii < n_sub_poly; ii++)
33131 boundary_marked_as_shared_boundary(dst_bnd_id_initial, ii))
33135 connecting_to_an_overlaped_boundary =
true;
33147 boundary_marked_as_shared_boundary(dst_bnd_id_initial, 0))
33150 connecting_to_an_overlaped_boundary =
true;
33156 #endif // #ifdef OOMPH_HAS_MPI
33161 if (!(connecting_to_an_split_boundary ||
33162 connecting_to_an_overlaped_boundary))
33166 poly_to_connect_pt = this->boundary_polyline_pt(dst_bnd_id_initial);
33176 if (!connecting_to_an_split_boundary)
33180 if (!connecting_to_an_overlaped_boundary)
33184 found_vertex_on_dst_boundary_initial =
33185 this->get_connected_vertex_number_on_destination_polyline(
33186 poly_to_connect_pt,
33187 src_vertex_coordinates_initial,
33188 n_vertex_connection_initial);
33201 #ifdef OOMPH_HAS_MPI
33208 Vector<TriangleMeshPolyLine*> tmp_vector_subpolylines =
33209 this->boundary_subpolylines(dst_bnd_id_initial);
33212 const unsigned nsub_poly = tmp_vector_subpolylines.size();
33214 if (nsub_poly <= 1)
33216 std::ostringstream error_message;
33218 <<
"The boundary (" << dst_bnd_id_initial <<
") was "
33219 <<
"marked to be splitted but\n"
33220 <<
"there are only ("<<nsub_poly<<
") polylines to "
33221 <<
"represent it.\n";
33222 throw OomphLibError(
33223 error_message.str(),
33224 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33225 OOMPH_EXCEPTION_LOCATION);
33236 if (!connecting_to_an_overlaped_boundary)
33244 for (
unsigned isub = 0; isub < nsub_poly; isub++)
33247 poly_to_connect_pt = tmp_vector_subpolylines[isub];
33249 found_vertex_on_dst_boundary_initial =
33250 this->get_connected_vertex_number_on_destination_polyline(
33251 poly_to_connect_pt,
33252 src_vertex_coordinates_initial,
33253 n_vertex_connection_initial);
33257 if (found_vertex_on_dst_boundary_initial)
33261 sub_poly_to_connect = isub;
33277 for (
unsigned isub = 0; isub < nsub_poly; isub++)
33282 boundary_marked_as_shared_boundary(dst_bnd_id_initial, isub))
33285 poly_to_connect_pt = tmp_vector_subpolylines[isub];
33288 found_vertex_on_dst_boundary_initial =
33289 this->get_connected_vertex_number_on_destination_polyline(
33290 poly_to_connect_pt,
33291 src_vertex_coordinates_initial,
33292 n_vertex_connection_initial);
33295 if (found_vertex_on_dst_boundary_initial)
33299 sub_poly_to_connect = isub;
33310 #endif // #ifdef OOMPH_HAS_MPI
33314 if (!found_vertex_on_dst_boundary_initial)
33317 #ifdef OOMPH_HAS_MPI
33318 if (this->is_mesh_distributed())
33324 polyline_pt->suspend_initial_vertex_connected();
33328 resume_initial_connection_polyline_pt.push_back(polyline_pt);
33335 #endif // #ifdef OOMPH_HAS_MPI
33340 const unsigned bnd_id = polyline_pt->boundary_id();
33341 std::ostringstream error_message;
33343 <<
"INITIAL VERTEX CONNECTION\n"
33344 <<
"It was not possible to find the associated "
33345 <<
"vertex number on the destination boundary\n"
33346 <<
"The current boundary (" << bnd_id <<
") is marked to have"
33347 <<
"a connection at the\nINITIAL vertex ("
33348 << src_vertex_coordinates_initial[0] <<
","
33349 << src_vertex_coordinates_initial[1] <<
")\n"
33350 <<
"with boundary ("<< dst_bnd_id_initial <<
")\n"
33351 <<
"This is the list of vertices on the destination boundary\n";
33354 TriangleMeshPolyLine *dst_polyline =
33355 this->boundary_polyline_pt(dst_bnd_id_initial);
33357 const unsigned n_vertex_dst_boundary = dst_polyline->nvertex();
33359 for (
unsigned i = 0; i < n_vertex_dst_boundary; i++)
33361 Vector<double> current_vertex = dst_polyline->vertex_coordinate(i);
33364 << current_vertex[0] <<
", " << current_vertex[1] <<
")\n";
33366 throw OomphLibError(
33367 error_message.str(),
33368 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33369 OOMPH_EXCEPTION_LOCATION);
33378 polyline_pt->initial_vertex_connected_n_vertex() =
33379 n_vertex_connection_initial;
33382 polyline_pt->initial_vertex_connected_n_chunk() =
33383 sub_poly_to_connect;
33391 if (polyline_pt->is_final_vertex_connected())
33394 TriangleMeshPolyLine *poly_to_connect_pt = 0;
33397 const unsigned dst_bnd_id_final =
33398 polyline_pt->final_vertex_connected_bnd_id();
33401 const unsigned tmp_n_vertices = polyline_pt->nvertex();
33402 Vector<double> src_vertex_coordinates_final =
33403 polyline_pt->vertex_coordinate(tmp_n_vertices-1);
33408 #ifdef OOMPH_HAS_MPI
33409 if (this->is_mesh_distributed())
33412 const unsigned init_shd_bnd_id =
33413 this->initial_shared_boundary_id();
33415 if (dst_bnd_id_final >= init_shd_bnd_id)
33418 const unsigned bnd_id = polyline_pt->boundary_id();
33419 std::ostringstream error_message;
33421 <<
"FINAL VERTEX CONNECTION\n"
33422 <<
"The current original boundary is trying to connect to a\n"
33423 <<
"shared boundary, this is not allowed. In this case the\n"
33424 <<
"shared boundary should be the one that connects with the\n"
33425 <<
"original boundary\n"
33426 <<
"The current boundary (" << bnd_id <<
") is marked to have "
33427 <<
"a connection at the\nFINAL vertex ("
33428 << src_vertex_coordinates_final[0] <<
","
33429 << src_vertex_coordinates_final[1] <<
")\n"
33430 <<
"with boundary ("<< dst_bnd_id_final <<
")\n"
33431 <<
"This is the list of vertices on the destination boundary\n";
33434 TriangleMeshPolyLine *dst_polyline =
33435 this->boundary_polyline_pt(dst_bnd_id_final);
33437 const unsigned n_vertex_dst_boundary = dst_polyline->nvertex();
33439 for (
unsigned i = 0; i < n_vertex_dst_boundary; i++)
33441 Vector<double> current_vertex = dst_polyline->vertex_coordinate(i);
33443 <<
"Vertex#("<<i<<
"): ("
33444 << current_vertex[0] <<
", " << current_vertex[1] <<
")\n";
33446 throw OomphLibError(
33447 error_message.str(),
33448 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33449 OOMPH_EXCEPTION_LOCATION);
33453 #endif // #ifdef OOMPH_HAS_MPI
33455 #endif // #ifdef PARANOID
33459 bool found_vertex_on_dst_boundary_final =
false;
33463 unsigned sub_poly_to_connect = 0;
33466 unsigned n_vertex_connection_final = 0;
33471 bool connecting_to_an_split_boundary =
false;
33475 bool connecting_to_an_overlaped_boundary =
false;
33477 #ifdef OOMPH_HAS_MPI
33478 if (this->is_mesh_distributed())
33483 if (this->boundary_was_splitted(dst_bnd_id_final))
33485 connecting_to_an_split_boundary =
true;
33494 if (connecting_to_an_split_boundary)
33498 const unsigned n_sub_poly =
33499 this->nboundary_subpolylines(dst_bnd_id_final);
33503 for (
unsigned ii =0; ii < n_sub_poly; ii++)
33506 boundary_marked_as_shared_boundary(dst_bnd_id_final, ii))
33510 connecting_to_an_overlaped_boundary =
true;
33522 boundary_marked_as_shared_boundary(dst_bnd_id_final, 0))
33525 connecting_to_an_overlaped_boundary =
true;
33531 #endif // #ifdef OOMPH_HAS_MPI
33536 if (!(connecting_to_an_split_boundary ||
33537 connecting_to_an_overlaped_boundary))
33541 poly_to_connect_pt = this->boundary_polyline_pt(dst_bnd_id_final);
33551 if (!connecting_to_an_split_boundary)
33555 if (!connecting_to_an_overlaped_boundary)
33559 found_vertex_on_dst_boundary_final =
33560 this->get_connected_vertex_number_on_destination_polyline(
33561 poly_to_connect_pt,
33562 src_vertex_coordinates_final,
33563 n_vertex_connection_final);
33576 #ifdef OOMPH_HAS_MPI
33583 Vector<TriangleMeshPolyLine*> tmp_vector_subpolylines =
33584 this->boundary_subpolylines(dst_bnd_id_final);
33587 const unsigned nsub_poly = tmp_vector_subpolylines.size();
33589 if (nsub_poly <= 1)
33591 std::ostringstream error_message;
33593 <<
"The boundary (" << dst_bnd_id_final <<
") was "
33594 <<
"marked to be splitted but\n"
33595 <<
"there are only ("<<nsub_poly<<
") polylines to "
33596 <<
"represent it.\n";
33597 throw OomphLibError(
33598 error_message.str(),
33599 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33600 OOMPH_EXCEPTION_LOCATION);
33611 if (!connecting_to_an_overlaped_boundary)
33619 for (
unsigned isub = 0; isub < nsub_poly; isub++)
33622 poly_to_connect_pt = tmp_vector_subpolylines[isub];
33624 found_vertex_on_dst_boundary_final =
33625 this->get_connected_vertex_number_on_destination_polyline(
33626 poly_to_connect_pt,
33627 src_vertex_coordinates_final,
33628 n_vertex_connection_final);
33632 if (found_vertex_on_dst_boundary_final)
33636 sub_poly_to_connect = isub;
33652 for (
unsigned isub = 0; isub < nsub_poly; isub++)
33657 boundary_marked_as_shared_boundary(dst_bnd_id_final, isub))
33660 poly_to_connect_pt = tmp_vector_subpolylines[isub];
33663 found_vertex_on_dst_boundary_final =
33664 this->get_connected_vertex_number_on_destination_polyline(
33665 poly_to_connect_pt,
33666 src_vertex_coordinates_final,
33667 n_vertex_connection_final);
33670 if (found_vertex_on_dst_boundary_final)
33674 sub_poly_to_connect = isub;
33685 #endif // #ifdef OOMPH_HAS_MPI
33689 if (!found_vertex_on_dst_boundary_final)
33692 #ifdef OOMPH_HAS_MPI
33693 if (this->is_mesh_distributed())
33699 polyline_pt->suspend_final_vertex_connected();
33703 resume_final_connection_polyline_pt.push_back(polyline_pt);
33710 #endif // #ifdef OOMPH_HAS_MPI
33715 const unsigned bnd_id = polyline_pt->boundary_id();
33716 std::ostringstream error_message;
33718 <<
"FINAL VERTEX CONNECTION\n"
33719 <<
"It was not possible to find the associated "
33720 <<
"vertex number on the destination boundary\n"
33721 <<
"The current boundary (" << bnd_id <<
") is marked to have "
33722 <<
"a connection at the\nFINAL vertex ("
33723 << src_vertex_coordinates_final[0] <<
","
33724 << src_vertex_coordinates_final[1] <<
")\n"
33725 <<
"with boundary ("<< dst_bnd_id_final <<
")\n"
33726 <<
"This is the list of vertices on the destination boundary\n";
33729 TriangleMeshPolyLine *dst_polyline =
33730 this->boundary_polyline_pt(dst_bnd_id_final);
33732 const unsigned n_vertex_dst_boundary = dst_polyline->nvertex();
33734 for (
unsigned i = 0; i < n_vertex_dst_boundary; i++)
33736 Vector<double> current_vertex = dst_polyline->vertex_coordinate(i);
33738 <<
"Vertex#("<<i<<
"): ("
33739 << current_vertex[0] <<
", " << current_vertex[1] <<
")\n";
33741 throw OomphLibError(
33742 error_message.str(),
33743 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33744 OOMPH_EXCEPTION_LOCATION);
33752 polyline_pt->final_vertex_connected_n_vertex() =
33753 n_vertex_connection_final;
33756 polyline_pt->final_vertex_connected_n_chunk() =
33757 sub_poly_to_connect;
33773 template<
class ELEMENT>
33775 Vector<TriangleMeshPolyLine*> &resume_initial_connection_polyline_pt,
33776 Vector<TriangleMeshPolyLine*> &resume_final_connection_polyline_pt)
33780 const unsigned n_initial_poly =
33781 resume_initial_connection_polyline_pt.size();
33784 for (
unsigned p = 0; p < n_initial_poly; p++)
33787 TriangleMeshPolyLine* tmp_poly_pt =
33788 resume_initial_connection_polyline_pt[p];
33790 tmp_poly_pt->resume_initial_vertex_connected();
33795 const unsigned n_final_poly =
33796 resume_final_connection_polyline_pt.size();
33799 for (
unsigned p = 0; p < n_final_poly; p++)
33802 TriangleMeshPolyLine* tmp_poly_pt =
33803 resume_final_connection_polyline_pt[p];
33805 tmp_poly_pt->resume_final_vertex_connected();
33809 resume_initial_connection_polyline_pt.clear();
33810 resume_final_connection_polyline_pt.clear();
33818 template<
class ELEMENT>
33821 Vector<double> &vertex_coordinates,
33822 const unsigned &dst_bnd_id,
33823 unsigned &vertex_number)
33826 bool found_associated_vertex_number =
false;
33829 TriangleMeshPolyLine *dst_polyline =
33830 this->boundary_polyline_pt(dst_bnd_id);
33832 const unsigned n_vertices = dst_polyline->nvertex();
33836 for (
unsigned i = 0; i < n_vertices; i++)
33839 Vector<double> current_vertex =
33840 dst_polyline->vertex_coordinate(i);
33843 (vertex_coordinates[0] - current_vertex[0])*
33844 (vertex_coordinates[0] - current_vertex[0])
33846 (vertex_coordinates[1] - current_vertex[1])*
33847 (vertex_coordinates[1] - current_vertex[1]);
33849 error = sqrt(error);
33852 ToleranceForVertexMismatchInPolygons::Tolerable_error)
33855 found_associated_vertex_number =
true;
33861 return found_associated_vertex_number;
33874 template<
class ELEMENT>
33877 const bool& check_only)
33885 if (this->is_mesh_distributed() && !check_only)
33887 std::stringstream error_message;
33889 <<
"The updating of polygons of a distributed mesh can ONLY be\n"
33890 <<
"performed using the element's area associated to the halo(ed)\n"
33892 <<
"1) Make sure you have enabled the parallel mesh adaptation\n"
33893 <<
"option if you are working with a distributed mesh, OR\n"
33894 <<
"2) Make sure to call the update_..._using_elements_area() methods\n"
33895 <<
"if the mesh is marked as distributed\n\n";
33896 throw OomphLibError(error_message.str(),
33897 OOMPH_CURRENT_FUNCTION,
33898 OOMPH_EXCEPTION_LOCATION);
33904 bool unrefinement_was_performed=
false;
33905 bool refinement_was_performed=
false;
33906 bool max_length_applied =
false;
33909 const unsigned n_polyline = polygon_pt->npolyline();
33914 Vector<Mesh*> face_mesh_pt;
33915 get_face_mesh_representation(polygon_pt,face_mesh_pt);
33919 Vector<double> vertex_coord(3);
33920 Vector<double> bound_left(1);
33921 Vector<double> bound_right(1);
33923 for(
unsigned p=0;p<n_polyline;p++)
33928 std::set<Vector<double> > vertex_nodes;
33931 const unsigned bound = polygon_pt->curve_section_pt(p)->boundary_id();
33934 const unsigned chunk = polygon_pt->curve_section_pt(p)->boundary_chunk();
33937 unsigned n_face_element = face_mesh_pt[p]->nelement();
33938 for(
unsigned e=0;e<n_face_element;++e)
33940 FiniteElement* el_pt = face_mesh_pt[p]->finite_element_pt(e);
33942 #ifdef OOMPH_HAS_MPI
33944 if (this->is_mesh_distributed() && el_pt->is_halo()) {
continue;}
33947 unsigned n_node = el_pt->nnode();
33952 el_pt->node_pt(0)->get_coordinates_on_boundary(bound,bound_left);
33953 vertex_coord[0] = bound_left[0];
33956 for(
unsigned i=0;i<2;i++)
33958 vertex_coord[i+1] = el_pt->node_pt(0)->x(i);
33960 vertex_nodes.insert(vertex_coord);
33965 el_pt->node_pt(n_node-1)->
33966 get_coordinates_on_boundary(bound,bound_right);
33967 vertex_coord[0] = bound_right[0];
33970 for(
unsigned i=0;i<2;i++)
33972 vertex_coord[i+1] = el_pt->node_pt(n_node-1)->x(i);
33974 vertex_nodes.insert(vertex_coord);
33979 unsigned n_poly_vertex = vertex_nodes.size();
33980 Vector<Vector<double> > tmp_vector_vertex_node(n_poly_vertex);
33982 for(std::set<Vector<double> >::iterator it = vertex_nodes.begin();
33983 it!=vertex_nodes.end();++it)
33985 tmp_vector_vertex_node[count].resize(3);
33986 tmp_vector_vertex_node[count][0] = (*it)[0];
33987 tmp_vector_vertex_node[count][1] = (*it)[1];
33988 tmp_vector_vertex_node[count][2] = (*it)[2];
33993 unsigned n_vertex=tmp_vector_vertex_node.size();
33997 double unrefinement_tolerance=
33998 polygon_pt->polyline_pt(p)->unrefinement_tolerance();
34003 if (unrefinement_tolerance>0.0 && n_vertex>=3)
34005 unrefinement_was_performed =
34006 unrefine_boundary(bound, chunk, tmp_vector_vertex_node,
34007 unrefinement_tolerance, check_only);
34012 if (check_only && unrefinement_was_performed)
34016 for(
unsigned p=0;p<n_polyline;p++)
34018 face_mesh_pt[p]->flush_node_storage();
34019 delete face_mesh_pt[p];
34028 n_vertex=tmp_vector_vertex_node.size();
34033 double refinement_tolerance=
34034 polygon_pt->polyline_pt(p)->refinement_tolerance();
34035 if (refinement_tolerance>0.0 && n_vertex >= 2)
34037 refinement_was_performed =
34038 refine_boundary(face_mesh_pt[p], tmp_vector_vertex_node,
34039 refinement_tolerance, check_only);
34044 if (check_only && refinement_was_performed)
34048 for(
unsigned p=0;p<n_polyline;p++)
34050 face_mesh_pt[p]->flush_node_storage();
34051 delete face_mesh_pt[p];
34061 n_vertex=tmp_vector_vertex_node.size();
34066 double maximum_length = polygon_pt->polyline_pt(p)->maximum_length();
34067 if (maximum_length > 0.0 && n_vertex >= 2)
34069 max_length_applied =
34070 apply_max_length_constraint(face_mesh_pt[p],
34071 tmp_vector_vertex_node,
34076 if (check_only && max_length_applied)
34080 for(
unsigned p=0;p<n_polyline;p++)
34082 face_mesh_pt[p]->flush_node_storage();
34083 delete face_mesh_pt[p];
34092 n_vertex=tmp_vector_vertex_node.size();
34093 Vector<Vector<double> > vector_vertex_node(n_vertex);
34095 for(
unsigned i=0;i<n_vertex;i++)
34097 vector_vertex_node[i].resize(2);
34098 vector_vertex_node[i][0]=tmp_vector_vertex_node[i][1];
34099 vector_vertex_node[i][1]=tmp_vector_vertex_node[i][2];
34102 #ifdef OOMPH_HAS_MPI
34106 if (!this->is_mesh_distributed())
34109 if ( (p > 0) && !check_only )
34112 Vector<double> final_vertex_of_previous_segment;
34113 unsigned n_prev_vertex =
34114 polygon_pt->curve_section_pt(p-1)->nvertex();
34115 final_vertex_of_previous_segment =
34116 polygon_pt->polyline_pt(p-1)->
34117 vertex_coordinate(n_prev_vertex-1);
34119 unsigned prev_seg_boundary_id =
34120 polygon_pt->curve_section_pt(p-1)->boundary_id();
34124 double error = 0.0;
34125 for(
unsigned i=0;i<2;i++)
34127 const double dist =
34128 final_vertex_of_previous_segment[i] -
34129 (*vector_vertex_node.begin())[i];
34130 error += dist*dist;
34132 error = sqrt(error);
34136 if(error > ToleranceForVertexMismatchInPolygons::Tolerable_error)
34140 double rev_error = 0.0;
34141 for(
unsigned i=0;i<2;i++)
34143 const double dist =
34144 final_vertex_of_previous_segment[i] -
34145 (*--vector_vertex_node.end())[i];
34146 rev_error += dist*dist;
34148 rev_error = sqrt(rev_error);
34151 ToleranceForVertexMismatchInPolygons::Tolerable_error)
34161 Vector<double> initial_vertex_of_previous_segment;
34163 initial_vertex_of_previous_segment =
34164 polygon_pt->polyline_pt(p-1)->
34165 vertex_coordinate(0);
34167 unsigned prev_seg_boundary_id =
34168 polygon_pt->curve_section_pt(p-1)->boundary_id();
34172 double error = 0.0;
34173 for(
unsigned i=0;i<2;i++)
34175 const double dist =
34176 initial_vertex_of_previous_segment[i] -
34177 (*vector_vertex_node.begin())[i];
34178 error += dist*dist;
34180 error = sqrt(error);
34184 if(error > ToleranceForVertexMismatchInPolygons::Tolerable_error)
34188 double rev_error = 0.0;
34189 for(
unsigned i=0;i<2;i++)
34191 const double dist =
34192 initial_vertex_of_previous_segment[i] -
34193 (*--vector_vertex_node.end())[i];
34194 rev_error += dist*dist;
34196 rev_error = sqrt(rev_error);
34200 ToleranceForVertexMismatchInPolygons::Tolerable_error)
34202 std::ostringstream error_stream;
34204 <<
"The distance between the first node of the current\n"
34205 <<
"line segment (boundary " << bound <<
") and either end of "
34206 <<
"the previous line segment\n"
34207 <<
"(boundary " << prev_seg_boundary_id <<
") is bigger than "
34208 <<
"the desired tolerance " <<
34209 ToleranceForVertexMismatchInPolygons::Tolerable_error <<
".\n"
34210 <<
"This suggests that the polylines defining the polygonal\n"
34211 <<
"representation are not properly ordered.\n"
34212 <<
"Fail on last vertex of polyline: ("
34213 << prev_seg_boundary_id<<
") and\nfirst vertex of polyline ("
34214 << bound <<
").\nThis should have failed when first trying to "
34215 <<
"construct the\npolygon.\n";
34216 throw OomphLibError(error_stream.str(),
34217 OOMPH_CURRENT_FUNCTION,
34218 OOMPH_EXCEPTION_LOCATION);
34225 std::reverse(vector_vertex_node.begin(),
34226 vector_vertex_node.end());
34228 polygon_pt->polyline_pt(p-1)->reverse();
34234 polygon_pt->polyline_pt(p-1)->reverse();
34240 std::ostringstream error_stream;
34242 <<
"The distance between the first node of the current\n"
34243 <<
"line segment (boundary " << bound <<
") and either end of "
34244 <<
"the previous line segment\n"
34245 <<
"(boundary " << prev_seg_boundary_id <<
") is bigger than the "
34246 <<
"desired tolerance " <<
34247 ToleranceForVertexMismatchInPolygons::Tolerable_error <<
".\n"
34248 <<
"This suggests that the polylines defining the polygonal\n"
34249 <<
"representation are not properly ordered.\n"
34250 <<
"Fail on last vertex of polyline: (" << prev_seg_boundary_id
34251 <<
") and\nfirst vertex of polyline (" << bound <<
").\n"
34252 <<
"This should have failed when first trying to construct the\n"
34254 throw OomphLibError(error_stream.str(),
34255 OOMPH_CURRENT_FUNCTION,
34256 OOMPH_EXCEPTION_LOCATION);
34262 std::reverse(vector_vertex_node.begin(),vector_vertex_node.end());
34273 TriangleMeshPolyLine *tmp_polyline_pt =
34274 new TriangleMeshPolyLine(vector_vertex_node,bound);
34278 TriangleMeshCurveSection *tmp_curve_section_pt = tmp_polyline_pt;
34281 tmp_polyline_pt->set_unrefinement_tolerance(
34282 unrefinement_tolerance);
34283 tmp_polyline_pt->set_refinement_tolerance(
34284 refinement_tolerance);
34287 tmp_polyline_pt->set_maximum_length(maximum_length);
34291 this->copy_connection_information(polygon_pt->polyline_pt(p),
34292 tmp_curve_section_pt);
34297 bool delete_it_on_destructor =
false;
34299 std::set<TriangleMeshCurveSection*>::iterator it =
34300 this->Free_curve_section_pt.find(polygon_pt->curve_section_pt(p));
34302 if (it!=this->Free_curve_section_pt.end())
34304 this->Free_curve_section_pt.erase(it);
34305 delete polygon_pt->curve_section_pt(p);
34306 delete_it_on_destructor =
true;
34311 polygon_pt->curve_section_pt(p) = tmp_polyline_pt;
34314 this->Boundary_curve_section_pt[bound] = polygon_pt->curve_section_pt(p);
34316 if (delete_it_on_destructor)
34318 this->Free_curve_section_pt.insert(polygon_pt->curve_section_pt(p));
34327 for(
unsigned p=0;p<n_polyline;p++)
34329 face_mesh_pt[p]->flush_node_storage();
34330 delete face_mesh_pt[p];
34344 return (unrefinement_was_performed ||
34345 refinement_was_performed ||
34346 max_length_applied);
34360 template<
class ELEMENT>
34363 const bool& check_only)
34371 if (this->is_mesh_distributed() && !check_only)
34373 std::stringstream error_message;
34375 <<
"The updating of open curves of a distributed mesh can ONLY be\n"
34376 <<
"performed using the element's area associated to the halo(ed)\n"
34378 <<
"1) Make sure you have enabled the parallel mesh adaptation\n"
34379 <<
"option if you are working with a distributed mesh, OR\n"
34380 <<
"2) Make sure to call the update_..._using_elements_area() methods\n"
34381 <<
"if the mesh is marked as distributed\n\n";
34382 throw OomphLibError(error_message.str(),
34383 OOMPH_CURRENT_FUNCTION,
34384 OOMPH_EXCEPTION_LOCATION);
34390 bool unrefinement_was_performed=
false;
34391 bool refinement_was_performed=
false;
34392 bool max_length_applied =
false;
34395 const unsigned n_polyline = open_polyline_pt->ncurve_section();
34400 Vector<Mesh*> face_mesh_pt;
34401 get_face_mesh_representation(open_polyline_pt, face_mesh_pt);
34405 Vector<double> vertex_coord(3);
34406 Vector<double> bound_left(1);
34407 Vector<double> bound_right(1);
34409 for(
unsigned p=0;p<n_polyline;p++)
34414 std::set<Vector<double> > vertex_nodes;
34417 const unsigned bound =
34418 open_polyline_pt->curve_section_pt(p)->boundary_id();
34421 const unsigned chunk =
34422 open_polyline_pt->curve_section_pt(p)->boundary_chunk();
34425 unsigned n_face_element = face_mesh_pt[p]->nelement();
34428 for(
unsigned e=0;e<n_face_element;++e)
34430 FiniteElement* el_pt = face_mesh_pt[p]->finite_element_pt(e);
34431 unsigned n_node = el_pt->nnode();
34436 el_pt->node_pt(0)->get_coordinates_on_boundary(bound,bound_left);
34437 vertex_coord[0] = bound_left[0];
34440 for(
unsigned i=0;i<2;i++)
34442 vertex_coord[i+1] = el_pt->node_pt(0)->x(i);
34444 vertex_nodes.insert(vertex_coord);
34449 el_pt->node_pt(n_node-1)->get_coordinates_on_boundary(bound,bound_right);
34450 vertex_coord[0] = bound_right[0];
34453 for(
unsigned i=0;i<2;i++)
34455 vertex_coord[i+1] = el_pt->node_pt(n_node-1)->x(i);
34457 vertex_nodes.insert(vertex_coord);
34462 unsigned n_poly_vertex = vertex_nodes.size();
34463 Vector<Vector<double> > tmp_vector_vertex_node(n_poly_vertex);
34465 for(std::set<Vector<double> >::iterator it = vertex_nodes.begin();
34466 it!=vertex_nodes.end();++it)
34468 tmp_vector_vertex_node[count].resize(3);
34469 tmp_vector_vertex_node[count][0] = (*it)[0];
34470 tmp_vector_vertex_node[count][1] = (*it)[1];
34471 tmp_vector_vertex_node[count][2] = (*it)[2];
34476 unsigned n_vertex=tmp_vector_vertex_node.size();
34480 double unrefinement_tolerance=
34481 open_polyline_pt->polyline_pt(p)->unrefinement_tolerance();
34486 if (unrefinement_tolerance>0.0 && n_vertex>=3)
34488 unrefinement_was_performed =
34489 unrefine_boundary(bound, chunk, tmp_vector_vertex_node,
34490 unrefinement_tolerance, check_only);
34495 if (check_only && unrefinement_was_performed)
34499 for(
unsigned p=0;p<n_polyline;p++)
34501 face_mesh_pt[p]->flush_node_storage();
34502 delete face_mesh_pt[p];
34512 n_vertex=tmp_vector_vertex_node.size();
34517 double refinement_tolerance=
34518 open_polyline_pt->polyline_pt(p)->refinement_tolerance();
34519 if (refinement_tolerance>0.0 && n_vertex >= 2)
34521 refinement_was_performed =
34522 refine_boundary(face_mesh_pt[p], tmp_vector_vertex_node,
34523 refinement_tolerance, check_only);
34528 if (check_only && refinement_was_performed)
34532 for(
unsigned p=0;p<n_polyline;p++)
34534 face_mesh_pt[p]->flush_node_storage();
34535 delete face_mesh_pt[p];
34545 n_vertex=tmp_vector_vertex_node.size();
34550 double maximum_length = open_polyline_pt->polyline_pt(p)->maximum_length();
34551 if (maximum_length > 0.0 && n_vertex >= 2)
34553 bool max_length_applied =
false;
34554 max_length_applied =
34555 apply_max_length_constraint(face_mesh_pt[p],
34556 tmp_vector_vertex_node,
34561 if (check_only && max_length_applied)
34565 for(
unsigned p=0;p<n_polyline;p++)
34567 face_mesh_pt[p]->flush_node_storage();
34568 delete face_mesh_pt[p];
34577 n_vertex=tmp_vector_vertex_node.size();
34578 Vector<Vector<double> > vector_vertex_node(n_vertex);
34580 for(
unsigned i=0;i<n_vertex;i++)
34582 vector_vertex_node[i].resize(2);
34583 vector_vertex_node[i][0]=tmp_vector_vertex_node[i][1];
34584 vector_vertex_node[i][1]=tmp_vector_vertex_node[i][2];
34587 #ifdef OOMPH_HAS_MPI
34591 if (!this->is_mesh_distributed())
34600 if( (p > 0) && !check_only )
34603 Vector<double> final_vertex_of_previous_segment;
34604 open_polyline_pt->polyline_pt(p-1)->
34605 final_vertex_coordinate(final_vertex_of_previous_segment);
34607 unsigned prev_seg_boundary_id =
34608 open_polyline_pt->curve_section_pt(p-1)->boundary_id();
34612 double error = 0.0;
34613 for(
unsigned i=0;i<2;i++)
34615 const double dist =
34616 final_vertex_of_previous_segment[i] -
34617 (*vector_vertex_node.begin())[i];
34618 error += dist*dist;
34620 error = sqrt(error);
34624 if(error > ToleranceForVertexMismatchInPolygons::Tolerable_error)
34629 for(
unsigned i=0;i<2;i++)
34631 const double dist =
34632 final_vertex_of_previous_segment[i] -
34633 (*--vector_vertex_node.end())[i];
34634 error += dist*dist;
34636 error = sqrt(error);
34638 if (error > ToleranceForVertexMismatchInPolygons::Tolerable_error)
34649 Vector<double> initial_vertex_of_previous_segment;
34650 open_polyline_pt->polyline_pt(p-1)->
34651 initial_vertex_coordinate(initial_vertex_of_previous_segment);
34656 for(
unsigned i=0;i<2;i++)
34658 const double dist =
34659 initial_vertex_of_previous_segment[i] -
34660 (*vector_vertex_node.begin())[i];
34661 error += dist*dist;
34663 error = sqrt(error);
34667 if(error > ToleranceForVertexMismatchInPolygons::Tolerable_error)
34672 for(
unsigned i=0;i<2;i++)
34674 const double dist =
34675 initial_vertex_of_previous_segment[i] -
34676 (*--vector_vertex_node.end())[i];
34677 error += dist*dist;
34679 error = sqrt(error);
34682 ToleranceForVertexMismatchInPolygons::Tolerable_error)
34684 std::ostringstream error_stream;
34686 <<
"The distance between the first node of the current\n"
34687 <<
"line segment (boundary " << bound
34688 <<
") and either end of the previous line segment\n"
34689 <<
"(boundary " << prev_seg_boundary_id <<
") is bigger than "
34690 <<
"the desired tolerance " <<
34691 ToleranceForVertexMismatchInPolygons::Tolerable_error<<
".\n"
34692 <<
"This suggests that the polylines defining the open "
34694 <<
"representation are not properly ordered.\n"
34695 <<
"Fail on last vertex of polyline: ("
34696 << prev_seg_boundary_id
34697 <<
") and\nfirst vertex of polyline (" << bound <<
").\n"
34698 <<
"This should have failed when first trying to construct\n"
34699 <<
"the open curve.\n";
34700 throw OomphLibError(error_stream.str(),
34701 OOMPH_CURRENT_FUNCTION,
34702 OOMPH_EXCEPTION_LOCATION);
34707 open_polyline_pt->polyline_pt(p-1)->reverse();
34709 std::reverse(vector_vertex_node.begin(),
34710 vector_vertex_node.end());
34716 open_polyline_pt->polyline_pt(p-1)->reverse();
34721 std::ostringstream error_stream;
34723 <<
"The distance between the first node of the current\n"
34724 <<
"line segment (boundary " << bound <<
") and either end of "
34725 <<
"the previous line segment\n"
34726 <<
"(boundary "<<prev_seg_boundary_id<<
") is bigger than the "
34727 <<
"desired tolerance " <<
34728 ToleranceForVertexMismatchInPolygons::Tolerable_error <<
".\n"
34729 <<
"This suggests that the polylines defining the polygonal\n"
34730 <<
"representation are not properly ordered.\n"
34731 <<
"Fail on last vertex of polyline: ("<<prev_seg_boundary_id
34732 <<
") and\nfirst vertex of polyline ("<<bound<<
").\n"
34733 <<
"This should have failed when first trying to construct the\n"
34735 throw OomphLibError(error_stream.str(),
34736 OOMPH_CURRENT_FUNCTION,
34737 OOMPH_EXCEPTION_LOCATION);
34743 std::reverse(vector_vertex_node.begin(),vector_vertex_node.end());
34756 TriangleMeshPolyLine *tmp_polyline =
34757 new TriangleMeshPolyLine(vector_vertex_node, bound);
34761 TriangleMeshCurveSection *tmp_curve_section = tmp_polyline;
34764 tmp_polyline->set_unrefinement_tolerance(
34765 unrefinement_tolerance);
34766 tmp_polyline->set_refinement_tolerance(
34767 refinement_tolerance);
34770 tmp_polyline->set_maximum_length(maximum_length);
34774 this->copy_connection_information(open_polyline_pt->polyline_pt(p),
34775 tmp_curve_section);
34777 std::set<TriangleMeshCurveSection*>::iterator it =
34778 this->Free_curve_section_pt.find(open_polyline_pt->curve_section_pt(p));
34780 bool delete_it_on_destructor =
false;
34782 if (it!=this->Free_curve_section_pt.end())
34785 this->Free_curve_section_pt.erase(it);
34786 delete open_polyline_pt->curve_section_pt(p);
34787 delete_it_on_destructor =
true;
34792 open_polyline_pt->curve_section_pt(p) = tmp_polyline;
34795 this->Boundary_curve_section_pt[bound] =
34796 open_polyline_pt->curve_section_pt(p);
34798 if (delete_it_on_destructor)
34800 this->Free_curve_section_pt.insert(
34801 open_polyline_pt->curve_section_pt(p));
34810 for(
unsigned p=0;p<n_polyline;p++)
34812 face_mesh_pt[p]->flush_node_storage();
34813 delete face_mesh_pt[p];
34827 return (unrefinement_was_performed ||
34828 refinement_was_performed ||
34829 max_length_applied);
34842 template<
class ELEMENT>
34846 Vector<Vector<double> > &vector_bnd_vertices,
34847 double &unrefinement_tolerance,
34848 const bool &check_only)
34851 std::set<Vector<double> > no_delete_vertex;
34854 const bool boundary_receive_connections =
34855 this->boundary_connections(b, c, no_delete_vertex);
34859 bool unrefinement_was_performed=
false;
34861 unsigned n_vertex = vector_bnd_vertices.size();
34865 unsigned counter=1;
34871 for(
unsigned i=1;i<=n_vertex-2;i+=2)
34874 double a_x=vector_bnd_vertices[i-1][1];
34875 double a_y=vector_bnd_vertices[i-1][2];
34876 double b_x=vector_bnd_vertices[i][1];
34877 double b_y=vector_bnd_vertices[i][2];
34878 double c_x=vector_bnd_vertices[i+1][1];
34879 double c_y=vector_bnd_vertices[i+1][2];
34886 double e=a*(a_x+b_x)+b*(a_y+b_y);
34887 double f=c*(a_x+c_x)+d*(a_y+c_y);
34889 double g=2.0*(a*(c_y-b_y)-b*(c_x-b_x));
34892 if (std::fabs(g)<1.0e-14)
34895 if(check_only) {
return true;}
34899 double p_x=(d*e-b*f)/g;
34900 double p_y=(a*f-c*e)/g;
34902 double r=sqrt(pow((a_x-p_x),2)+pow((a_y-p_y),2));
34904 double rhalfca_x=0.5*(a_x-c_x);
34905 double rhalfca_y=0.5*(a_y-c_y);
34907 double halfca_squared=pow(rhalfca_x,2)+pow(rhalfca_y,2);
34909 double sticky_out_bit=r-sqrt(std::fabs((r*r) - halfca_squared));
34914 if ((sticky_out_bit/(2.0*sqrt(halfca_squared)))<
34915 unrefinement_tolerance)
34918 if(check_only) {
return true;}
34924 if (do_it && boundary_receive_connections)
34927 for (std::set<Vector<double> >::iterator it = no_delete_vertex.begin();
34928 it != no_delete_vertex.end(); it++)
34932 const double x = (*it)[0];
34933 const double y = (*it)[1];
34934 double error = (b_x - x)*(b_x - x) + (b_y - y)*(b_y - y);
34935 error = sqrt(error);
34937 if(error<ToleranceForVertexMismatchInPolygons::Tolerable_error)
34951 vector_bnd_vertices[i].resize(0);
34970 if( (counter)==(n_vertex-1) )
34973 unsigned i=vector_bnd_vertices.size()-2;
34979 if(vector_bnd_vertices[counter-2].size()!=0)
34998 double a_x=vector_bnd_vertices[n][1];
34999 double a_y=vector_bnd_vertices[n][2];
35000 double b_x=vector_bnd_vertices[i][1];
35001 double b_y=vector_bnd_vertices[i][2];
35002 double c_x=vector_bnd_vertices[i+1][1];
35003 double c_y=vector_bnd_vertices[i+1][2];
35010 double e=a*(a_x+b_x)+b*(a_y+b_y);
35011 double f=c*(a_x+c_x)+d*(a_y+c_y);
35013 double g=2.0*(a*(c_y-b_y)-b*(c_x-b_x));
35016 if (std::fabs(g)<1.0e-14)
35019 if(check_only) {
return true;}
35023 double p_x=(d*e-b*f)/g;
35024 double p_y=(a*f-c*e)/g;
35026 double r=sqrt(pow((a_x-p_x),2)+pow((a_y-p_y),2));
35028 double rhalfca_x=0.5*(a_x-c_x);
35029 double rhalfca_y=0.5*(a_y-c_y);
35031 double halfca_squared=pow(rhalfca_x,2)+pow(rhalfca_y,2);
35033 double sticky_out_bit=r-sqrt(std::fabs((r*r) - halfca_squared));
35038 if ((sticky_out_bit/(2.0*sqrt(halfca_squared)))<
35039 unrefinement_tolerance)
35042 if(check_only) {
return true;}
35048 if (do_it && boundary_receive_connections)
35051 for (std::set<Vector<double> >::iterator it = no_delete_vertex.begin();
35052 it != no_delete_vertex.end(); it++)
35056 const double x = (*it)[0];
35057 const double y = (*it)[1];
35058 double error = (b_x - x)*(b_x - x) + (b_y - y)*(b_y - y);
35059 error = sqrt(error);
35062 ToleranceForVertexMismatchInPolygons::Tolerable_error)
35076 vector_bnd_vertices[i].resize(0);
35082 Vector<Vector<double> > compact_vector;
35083 compact_vector.reserve(n_vertex);
35084 for (
unsigned i=0;i<n_vertex;i++)
35087 if (vector_bnd_vertices[i].size()!=0)
35089 compact_vector.push_back(vector_bnd_vertices[i]);
35094 n_vertex =compact_vector.size();
35100 if( n_vertex != vector_bnd_vertices.size() )
35102 unrefinement_was_performed=
true;
35106 vector_bnd_vertices.resize(n_vertex);
35107 for(
unsigned i=0;i<n_vertex;i++)
35109 vector_bnd_vertices[i].resize(3);
35110 vector_bnd_vertices[i][0]=compact_vector[i][0];
35111 vector_bnd_vertices[i][1]=compact_vector[i][1];
35112 vector_bnd_vertices[i][2]=compact_vector[i][2];
35115 return unrefinement_was_performed;
35127 template<
class ELEMENT>
35130 Vector<Vector<double> > &vector_bnd_vertices,
35131 double &refinement_tolerance,
35132 const bool &check_only)
35136 bool refinement_was_performed=
false;
35140 MeshAsGeomObject* mesh_geom_obj_pt=
new MeshAsGeomObject(face_mesh_pt);
35143 unsigned n_vertex=vector_bnd_vertices.size();
35147 Vector<Vector<double> > extended_vector;
35151 extended_vector.reserve(2*n_vertex);
35154 for(
unsigned inod=0;inod<n_vertex-1;inod++)
35157 double zeta_left=vector_bnd_vertices[inod][0];
35160 Vector<double> R_left(2);
35161 for(
unsigned i=0;i<2;i++)
35163 R_left[i]=vector_bnd_vertices[inod][i+1];
35167 double zeta_right=vector_bnd_vertices[inod+1][0];
35170 Vector<double> R_right(2);
35171 for(
unsigned i=0;i<2;i++)
35173 R_right[i]=vector_bnd_vertices[inod+1][i+1];
35177 Vector<double> zeta_mid(1);
35178 zeta_mid[0]=0.5*(zeta_left+zeta_right);
35182 Vector<double> R_mid(2);
35183 mesh_geom_obj_pt->position(zeta_mid,R_mid);
35187 Vector<double> R_mid_polygon(2);
35188 for(
unsigned i=0;i<2;i++)
35190 R_mid_polygon[i]=0.5*(R_right[i]+R_left[i]);
35195 double distance=sqrt((R_mid[0]-R_mid_polygon[0])*
35196 (R_mid[0]-R_mid_polygon[0])+
35197 (R_mid[1]-R_mid_polygon[1])*
35198 (R_mid[1]-R_mid_polygon[1]));
35201 double length=sqrt((R_right[0]-R_left[0])*(R_right[0]-R_left[0])+
35202 (R_right[1]-R_left[1])*(R_right[1]-R_left[1]));
35208 if((distance/length) > refinement_tolerance)
35215 delete mesh_geom_obj_pt;
35219 Vector<double> new_node(3);
35220 new_node[0]=zeta_mid[0];
35221 new_node[1]=R_mid[0];
35222 new_node[2]=R_mid[1];
35225 extended_vector.push_back(vector_bnd_vertices[inod]);
35228 extended_vector.push_back(new_node);
35235 extended_vector.push_back(vector_bnd_vertices[inod]);
35240 extended_vector.push_back(vector_bnd_vertices[n_vertex-1]);
35243 n_vertex=extended_vector.size();
35248 if( n_vertex != vector_bnd_vertices.size() )
35250 refinement_was_performed=
true;
35254 vector_bnd_vertices.resize(n_vertex);
35255 for(
unsigned i=0;i<n_vertex;i++)
35257 vector_bnd_vertices[i].resize(3);
35258 vector_bnd_vertices[i][0]=extended_vector[i][0];
35259 vector_bnd_vertices[i][1]=extended_vector[i][1];
35260 vector_bnd_vertices[i][2]=extended_vector[i][2];
35265 delete mesh_geom_obj_pt;
35267 return refinement_was_performed;
35277 template<
class ELEMENT>
35280 Vector<Vector<double> > &vector_bnd_vertices,
35281 double &max_length_constraint)
35285 bool max_length_applied=
false;
35289 MeshAsGeomObject* mesh_geom_obj_pt=
new MeshAsGeomObject(face_mesh_pt);
35292 unsigned n_vertex=vector_bnd_vertices.size();
35296 Vector<Vector<double> > extended_vector;
35299 for(
unsigned inod=0;inod<n_vertex-1;inod++)
35302 double zeta_left=vector_bnd_vertices[inod][0];
35305 Vector<double> R_left(2);
35306 for(
unsigned i=0;i<2;i++)
35308 R_left[i]=vector_bnd_vertices[inod][i+1];
35312 double zeta_right=vector_bnd_vertices[inod+1][0];
35315 Vector<double> R_right(2);
35316 for(
unsigned i=0;i<2;i++)
35318 R_right[i]=vector_bnd_vertices[inod+1][i+1];
35322 extended_vector.push_back(vector_bnd_vertices[inod]);
35326 double length=std::fabs(zeta_right-zeta_left);
35329 if (length > max_length_constraint)
35331 double n_pts = length/max_length_constraint;
35333 unsigned n_points =
static_cast<unsigned>(n_pts);
35334 double zeta_increment = (zeta_right-zeta_left)/((
double)n_points+1);
35336 Vector<double> zeta(1);
35338 for(
unsigned s=1;
s<n_points+1;
s++)
35341 zeta[0]= zeta_left + zeta_increment*double(
s);
35342 Vector<double> vertex(2);
35343 mesh_geom_obj_pt->position(zeta, vertex);
35346 Vector<double> new_node(3);
35347 new_node[0]=zeta[0];
35348 new_node[1]=vertex[0];
35349 new_node[2]=vertex[1];
35352 extended_vector.push_back(new_node);
35358 extended_vector.push_back(vector_bnd_vertices[n_vertex-1]);
35361 n_vertex=extended_vector.size();
35366 if( n_vertex != vector_bnd_vertices.size() )
35368 max_length_applied =
true;
35372 vector_bnd_vertices.resize(n_vertex);
35373 for(
unsigned i=0;i<n_vertex;i++)
35375 vector_bnd_vertices[i].resize(3);
35376 vector_bnd_vertices[i][0]=extended_vector[i][0];
35377 vector_bnd_vertices[i][1]=extended_vector[i][1];
35378 vector_bnd_vertices[i][2]=extended_vector[i][2];
35383 delete mesh_geom_obj_pt;
35385 return max_length_applied;
35395 template<
class ELEMENT>
35398 const unsigned &boundary_id,
35399 Mesh* face_mesh_pt)
35406 this->
template build_face_mesh<ELEMENT,FaceElementAsGeomObject>
35407 (boundary_id,face_mesh_pt);
35410 unsigned n_element = face_mesh_pt->nelement();
35412 for(
unsigned e=0;e<n_element;e++)
35416 FaceElementAsGeomObject<ELEMENT>* el_pt=
35417 dynamic_cast<FaceElementAsGeomObject<ELEMENT>*
>
35418 (face_mesh_pt->element_pt(e));
35421 el_pt->set_boundary_number_in_bulk_mesh(boundary_id);
35432 template<
class ELEMENT>
35435 const unsigned &boundary_id,
35436 Mesh* face_mesh_pt,
35437 std::map<FiniteElement*, bool> &is_inverted,
35438 bool &inverted_face_mesh)
35440 Mesh *tmp_unsorted_face_mesh_pt =
new Mesh();
35443 create_unsorted_face_mesh_representation(
35444 boundary_id, tmp_unsorted_face_mesh_pt);
35454 std::list<FiniteElement*> sorted_el_pt;
35455 FiniteElement* el_pt = tmp_unsorted_face_mesh_pt->finite_element_pt(0);
35456 sorted_el_pt.push_back(el_pt);
35459 unsigned nnod=el_pt->nnode();
35462 unsigned count_done=0;
35465 unsigned n_face_element = tmp_unsorted_face_mesh_pt->nelement();
35468 std::map<FiniteElement*,bool> done_el;
35470 is_inverted.clear();
35473 for (
unsigned ee=1;ee<n_face_element;ee++)
35477 for (
unsigned e=1;e<n_face_element;e++)
35480 el_pt=tmp_unsorted_face_mesh_pt->finite_element_pt(e);
35483 if (!done_el[el_pt])
35486 FiniteElement* first_el_pt=(*sorted_el_pt.begin());
35487 std::list<FiniteElement*>::iterator it=sorted_el_pt.end();
35489 FiniteElement* last_el_pt=*it;
35492 Node* left_node_pt=first_el_pt->node_pt(0);
35493 if (is_inverted[first_el_pt])
35495 left_node_pt=first_el_pt->node_pt(nnod-1);
35497 Node* right_node_pt=last_el_pt->node_pt(nnod-1);
35498 if (is_inverted[last_el_pt])
35500 right_node_pt=last_el_pt->node_pt(0);
35504 if (left_node_pt==el_pt->node_pt(nnod-1))
35506 sorted_el_pt.push_front(el_pt);
35507 done_el[el_pt]=
true;
35509 is_inverted[el_pt]=
false;
35513 else if (left_node_pt==el_pt->node_pt(0))
35515 sorted_el_pt.push_front(el_pt);
35516 done_el[el_pt]=
true;
35518 is_inverted[el_pt]=
true;
35522 else if(right_node_pt==el_pt->node_pt(0))
35524 sorted_el_pt.push_back(el_pt);
35525 done_el[el_pt]=
true;
35527 is_inverted[el_pt]=
false;
35531 else if (right_node_pt==el_pt->node_pt(nnod-1))
35533 sorted_el_pt.push_back(el_pt);
35534 done_el[el_pt]=
true;
35536 is_inverted[el_pt]=
true;
35539 if (done_el[el_pt])
35548 if (count_done!=(n_face_element-1))
35550 std::ostringstream error_message;
35552 <<
"When ordering FaceElements on "
35553 <<
"boundary " << boundary_id <<
" only managed to order \n" << count_done
35554 <<
" of " << n_face_element <<
" face elements.\n"
35556 throw OomphLibError(
35557 error_message.str(),
35558 OOMPH_CURRENT_FUNCTION,
35559 OOMPH_EXCEPTION_LOCATION);
35566 for (std::list<FiniteElement*>::iterator it=sorted_el_pt.begin();
35567 it!=sorted_el_pt.end();it++)
35570 FiniteElement* el_pt=*it;
35573 face_mesh_pt->add_element_pt(el_pt);
35583 TriangleMeshPolyLine *bnd_polyline =
35584 this->Boundary_curve_section_pt[boundary_id];
35587 Vector<double> first_vertex =
35588 bnd_polyline->vertex_coordinate(0);
35592 FiniteElement* first_el_pt =
35593 face_mesh_pt->finite_element_pt(0);
35596 unsigned n_node = first_el_pt->nnode();
35599 Node* first_node_pt = first_el_pt->node_pt(0);
35600 if (is_inverted[first_el_pt])
35602 first_node_pt = first_el_pt->node_pt(n_node-1);
35605 double error = (first_node_pt->x(0) - first_vertex[0])*
35606 (first_node_pt->x(0) - first_vertex[0]) +
35607 (first_node_pt->x(1) - first_vertex[1])*
35608 (first_node_pt->x(1) - first_vertex[1]);
35610 error = sqrt(error);
35613 ToleranceForVertexMismatchInPolygons::Tolerable_error)
35615 inverted_face_mesh =
false;
35619 inverted_face_mesh =
true;
35629 template<
class ELEMENT>
35632 Vector<Mesh*>& face_mesh_pt)
35635 unsigned n_polyline = polygon_pt->npolyline();
35636 face_mesh_pt.resize(n_polyline);
35642 bool eligible_for_segment_redistribution=
true;
35645 for(
unsigned p=0;p<n_polyline;p++)
35650 polygon_pt->polyline_pt(p)->boundary_id();
35655 this->boundary_geom_object_pt(bound);
35656 if(geom_object_pt!=0)
35658 eligible_for_segment_redistribution=
false;
35661 face_mesh_pt[p] =
new Mesh();
35662 create_unsorted_face_mesh_representation(
35663 bound, face_mesh_pt[p]);
35667 if (!polygon_pt->is_redistribution_of_segments_between_polylines_enabled())
35673 if(this->nregion() > 1)
35675 std::ostringstream warn_message;
35677 <<
"Can't currently re-distribute segments between polylines if there\n"
35678 <<
"are multiple regions; returning..." << std::endl;
35679 OomphLibWarning(warn_message.str(),
35680 "RefineableTriangleMesh::get_face_mesh_representation()",
35681 OOMPH_EXCEPTION_LOCATION);
35686 if (!eligible_for_segment_redistribution)
35688 std::ostringstream warn_message;
35690 <<
"Over-ruling re-distribution of segments between polylines\n"
35691 <<
"because at least one boundary is associated with a GeomObject."
35692 <<
"Returning..." << std::endl;
35693 OomphLibWarning(warn_message.str(),
35694 "RefineableTriangleMesh::get_face_mesh_representation()",
35695 OOMPH_EXCEPTION_LOCATION);
35700 Vector<Mesh*> ordered_face_mesh_pt(n_polyline);
35703 double s_total=0.0;
35707 Vector<Node*> first_polyline_node_pt(n_polyline);
35708 Vector<Node*> last_polyline_node_pt(n_polyline);
35709 std::vector<bool> is_reversed(n_polyline,
false);
35712 for(
unsigned p=0;p<n_polyline;p++)
35719 std::list<FiniteElement*> ordered_el_pt;
35720 FiniteElement* el_pt=face_mesh_pt[p]->finite_element_pt(0);
35721 ordered_el_pt.push_back(el_pt);
35724 unsigned nnod=el_pt->nnode();
35727 first_polyline_node_pt[p]=el_pt->node_pt(0);
35728 last_polyline_node_pt[p]=el_pt->node_pt(nnod-1);
35731 unsigned count_done=0;
35734 unsigned n_face_element = face_mesh_pt[p]->nelement();
35738 polygon_pt->polyline_pt(p)->boundary_id();
35741 std::map<FiniteElement*,bool> done_el;
35744 std::map<FiniteElement*,bool> is_inverted;
35747 for (
unsigned ee=1;ee<n_face_element;ee++)
35751 for (
unsigned e=1;e<n_face_element;e++)
35754 el_pt=face_mesh_pt[p]->finite_element_pt(e);
35757 if (!done_el[el_pt])
35760 FiniteElement* first_el_pt=(*ordered_el_pt.begin());
35761 std::list<FiniteElement*>::iterator it=ordered_el_pt.end();
35763 FiniteElement* last_el_pt=*it;
35766 Node* left_node_pt=first_el_pt->node_pt(0);
35767 if (is_inverted[first_el_pt])
35769 left_node_pt=first_el_pt->node_pt(nnod-1);
35771 Node* right_node_pt=last_el_pt->node_pt(nnod-1);
35772 if (is_inverted[last_el_pt])
35774 right_node_pt=last_el_pt->node_pt(0);
35778 if (left_node_pt==el_pt->node_pt(nnod-1))
35780 ordered_el_pt.push_front(el_pt);
35781 done_el[el_pt]=
true;
35783 is_inverted[el_pt]=
false;
35784 first_polyline_node_pt[p]=el_pt->node_pt(0);
35788 else if (left_node_pt==el_pt->node_pt(0))
35790 ordered_el_pt.push_front(el_pt);
35791 done_el[el_pt]=
true;
35793 is_inverted[el_pt]=
true;
35794 first_polyline_node_pt[p]=el_pt->node_pt(nnod-1);
35798 else if(right_node_pt==el_pt->node_pt(0))
35800 ordered_el_pt.push_back(el_pt);
35801 done_el[el_pt]=
true;
35803 is_inverted[el_pt]=
false;
35804 last_polyline_node_pt[p]=el_pt->node_pt(nnod-1);
35808 else if (right_node_pt==el_pt->node_pt(nnod-1))
35810 ordered_el_pt.push_back(el_pt);
35811 done_el[el_pt]=
true;
35813 is_inverted[el_pt]=
true;
35814 last_polyline_node_pt[p]=el_pt->node_pt(0);
35817 if (done_el[el_pt])
35826 if (count_done!=(n_face_element-1))
35828 std::ostringstream error_message;
35830 <<
"When ordering FaceElements on "
35831 <<
"boundary " << bound <<
" only managed to order \n" << count_done
35832 <<
" of " << n_face_element <<
" face elements.\n"
35834 throw OomphLibError(
35835 error_message.str(),
35836 OOMPH_CURRENT_FUNCTION,
35837 OOMPH_EXCEPTION_LOCATION);
35841 ordered_face_mesh_pt[p] =
new Mesh;
35844 for (std::list<FiniteElement*>::iterator it=ordered_el_pt.begin();
35845 it!=ordered_el_pt.end();it++)
35848 FiniteElement* el_pt=*it;
35851 ordered_face_mesh_pt[p]->add_element_pt(el_pt);
35855 for(
unsigned e=0;e<n_face_element;++e)
35857 FiniteElement* el_pt=ordered_face_mesh_pt[p]->finite_element_pt(e);
35858 unsigned n_node=el_pt->nnode();
35859 double element_length_squared=0.0;
35860 for(
unsigned i=0;i<2;i++)
35862 element_length_squared += pow(el_pt->node_pt(n_node-1)->x(i)-
35863 el_pt->node_pt(0)->x(i),2);
35867 double element_length=sqrt(element_length_squared);
35870 s_total += element_length;
35874 face_mesh_pt[p]->flush_element_and_node_storage();
35878 if ((last_polyline_node_pt[0]==first_polyline_node_pt[1])||
35879 (last_polyline_node_pt[0]==last_polyline_node_pt[1]))
35881 is_reversed[0]=
false;
35883 else if ((first_polyline_node_pt[0]==first_polyline_node_pt[1])||
35884 (first_polyline_node_pt[0]==last_polyline_node_pt[1]))
35886 is_reversed[0]=
true;
35890 Vector<Mesh*> tmp_face_mesh_pt(n_polyline);
35891 std::vector<bool> mesh_done(n_polyline,
false);
35892 Vector<unsigned> old_polyline_number(n_polyline);
35895 tmp_face_mesh_pt[0]=ordered_face_mesh_pt[0];
35896 unsigned current=0;
35897 old_polyline_number[0]=0;
35898 unsigned count_found=0;
35901 for(
unsigned p=1;p<n_polyline;p++)
35903 Node* end_node_pt=last_polyline_node_pt[current];
35904 if (is_reversed[current])
35906 end_node_pt=first_polyline_node_pt[current];
35910 for(
unsigned pp=1;pp<n_polyline;pp++)
35912 if (!mesh_done[pp])
35915 if ((!is_reversed[current])&&
35916 (end_node_pt==first_polyline_node_pt[pp]))
35918 tmp_face_mesh_pt[p]=ordered_face_mesh_pt[pp];
35919 mesh_done[pp]=
true;
35920 is_reversed[pp]=
false;
35921 old_polyline_number[p]=pp;
35928 else if ((!is_reversed[current])&&
35929 (end_node_pt==last_polyline_node_pt[pp]))
35931 tmp_face_mesh_pt[p]=ordered_face_mesh_pt[pp];
35932 mesh_done[pp]=
true;
35933 is_reversed[pp]=
true;
35934 old_polyline_number[p]=pp;
35941 else if ((is_reversed[current])&&
35942 (end_node_pt==first_polyline_node_pt[pp]))
35944 tmp_face_mesh_pt[p]=ordered_face_mesh_pt[pp];
35945 mesh_done[pp]=
true;
35946 is_reversed[pp]=
false;
35947 old_polyline_number[p]=pp;
35954 else if ((is_reversed[current])&&
35955 (end_node_pt==last_polyline_node_pt[pp]))
35957 tmp_face_mesh_pt[p]=ordered_face_mesh_pt[pp];
35958 mesh_done[pp]=
true;
35959 is_reversed[pp]=
true;
35960 old_polyline_number[p]=pp;
35970 if (count_found!=n_polyline-1)
35972 std::ostringstream error_message;
35973 error_message <<
"Only found " << count_found
35974 <<
" out of " << n_polyline-1
35975 <<
" polylines to be fitted in.\n";
35976 throw OomphLibError(
35977 error_message.str(),
35978 OOMPH_CURRENT_FUNCTION,
35979 OOMPH_EXCEPTION_LOCATION);
35984 for (
unsigned i=0;i<n_polyline;i++)
35986 ordered_face_mesh_pt[i]=tmp_face_mesh_pt[i];
35992 unsigned new_face_id=0;
35996 std::map<Node*,std::map<unsigned,unsigned> >
35997 node_must_not_be_removed_from_boundary_flag;
36000 for(
unsigned p=0;p<n_polyline;p++)
36003 unsigned n_face_element = ordered_face_mesh_pt[p]->nelement();
36004 for (
unsigned e=0;e<n_face_element;e++)
36006 unsigned el_number=e;
36007 if (is_reversed[p])
36009 el_number=n_face_element-e-1;
36012 FiniteElement* el_pt=
36013 ordered_face_mesh_pt[p]->finite_element_pt(el_number);
36014 unsigned n_node = el_pt->nnode();
36017 double element_length_squared=0.0;
36018 for(
unsigned i=0;i<2;i++)
36020 element_length_squared += pow(el_pt->node_pt(n_node-1)->x(i)-
36021 el_pt->node_pt(0)->x(i),2);
36023 double element_length=sqrt(element_length_squared);
36026 s += element_length;
36030 if(
s < s_total/
double(n_polyline)+1e-6)
36033 face_mesh_pt[new_face_id]->add_element_pt(el_pt);
36035 unsigned bound_old =
36036 polygon_pt->polyline_pt(old_polyline_number[p])->boundary_id();
36038 unsigned bound_new =
36039 polygon_pt->polyline_pt(new_face_id)->boundary_id();
36042 for(
unsigned i=0;i<n_node;i++)
36045 Node* nod_pt=el_pt->node_pt(i);
36049 if(bound_new != bound_old)
36052 add_boundary_node(bound_new,nod_pt);
36056 node_must_not_be_removed_from_boundary_flag[nod_pt][bound_old]+=0;
36065 node_must_not_be_removed_from_boundary_flag[nod_pt][bound_old]+=1;
36077 if(new_face_id!=n_polyline-1)
36095 unsigned move_count=0;
36096 for (std::map<Node*,std::map<unsigned,unsigned> >::iterator
36097 it=node_must_not_be_removed_from_boundary_flag.begin();
36098 it!=node_must_not_be_removed_from_boundary_flag.end();it++)
36101 Node* nod_pt=(*it).first;
36104 for (std::map<unsigned,unsigned>::iterator
36105 it_2=(*it).second.begin();it_2!=(*it).second.end();it_2++)
36108 unsigned bound=(*it_2).first;
36111 if((*it_2).second==0)
36113 remove_boundary_node(bound,nod_pt);
36120 for(
unsigned p=0;p<n_polyline;p++)
36124 polygon_pt->polyline_pt(p)->boundary_id();
36127 unsigned n_face_element = face_mesh_pt[p]->nelement();
36128 for(
unsigned e=0;e<n_face_element;e++)
36131 FaceElementAsGeomObject<ELEMENT>* el_pt=
36132 dynamic_cast<FaceElementAsGeomObject<ELEMENT>*
>
36133 (face_mesh_pt[p]->element_pt(e));
36136 el_pt->set_boundary_number_in_bulk_mesh(bound);
36141 setup_boundary_element_info();
36144 for(
unsigned p=0;p<n_polyline;p++)
36148 polygon_pt->polyline_pt(p)->boundary_id();
36151 this->
template setup_boundary_coordinates<ELEMENT>(bound);
36155 for(
unsigned p=0;p<n_polyline;p++)
36160 ordered_face_mesh_pt[p]->flush_element_and_node_storage();
36161 delete ordered_face_mesh_pt[p];
36169 template<
class ELEMENT>
36172 TriangleMeshOpenCurve* open_polyline_pt,
36173 Vector<Mesh*>& face_mesh_pt)
36176 unsigned n_polyline = open_polyline_pt->ncurve_section();
36177 face_mesh_pt.resize(n_polyline);
36180 for(
unsigned p=0;p<n_polyline;p++)
36185 open_polyline_pt->curve_section_pt(p)->boundary_id();
36187 face_mesh_pt[p] =
new Mesh();
36188 create_unsorted_face_mesh_representation(
36189 bound, face_mesh_pt[p]);
36202 template <
class ELEMENT>
36205 &internal_point_coord,
36206 const bool& check_only)
36210 bool update_was_performed=
false;
36212 unsigned n_hole = internal_point_coord.size();
36213 for(
unsigned ihole=0;ihole<n_hole;ihole++)
36216 TriangleMeshPolygon*
const poly_pt
36217 = this->Internal_polygon_pt[ihole];
36222 if(poly_pt->can_update_reference_configuration())
36224 poly_pt->reset_reference_configuration();
36227 internal_point_coord[ihole].resize(2);
36230 internal_point_coord[ihole]=poly_pt->internal_point();
36241 bool update_necessary=
36242 this->update_polygon_using_face_mesh(poly_pt,check_only);
36245 if(update_necessary)
36255 update_was_performed=
36256 this->update_polygon_using_face_mesh(poly_pt);
36260 if (!poly_pt->internal_point().empty())
36264 if(poly_pt->is_internal_point_fixed())
36267 internal_point_coord[ihole]=poly_pt->internal_point();
36274 if(this->Internal_hole_point_update_fct_pt!=0)
36276 this->Internal_hole_point_update_fct_pt(ihole,poly_pt);
36282 Vector<double> vertex_coord;
36283 unsigned n_polyline = poly_pt->npolyline();
36286 vertex_coord.resize(2);
36287 internal_point_coord[ihole].resize(2);
36291 internal_point_coord[ihole][0] = 0.0;
36292 internal_point_coord[ihole][1] = 0.0;
36294 for(
unsigned p=0;p<n_polyline;p++)
36296 Vector<double> poly_ave(2,0.0);
36298 unsigned n_vertex = poly_pt->polyline_pt(p)->nvertex();
36299 for(
unsigned v=0;v<n_vertex;v++)
36301 vertex_coord = poly_pt->polyline_pt(p)->vertex_coordinate(v);
36302 for(
unsigned i=0;i<2;i++)
36304 poly_ave[i] += vertex_coord[i];
36309 for(
unsigned i=0;i<2;i++)
36311 internal_point_coord[ihole][i] += poly_ave[i]/n_vertex;
36316 for(
unsigned i=0;i<2;i++)
36318 internal_point_coord[ihole][i] /= n_polyline;
36363 poly_pt->internal_point() = internal_point_coord[ihole];
36382 return update_was_performed;
36391 template<
class ELEMENT>
36394 const std::string& poly_file_name)
36400 std::ifstream node_file(node_file_name.c_str(),std::ios_base::in);
36403 if(!node_file.is_open())
36405 std::string error_msg(
"Failed to open node file: ");
36406 error_msg +=
"\"" + node_file_name +
"\".";
36407 throw OomphLibError(error_msg, OOMPH_CURRENT_FUNCTION,
36408 OOMPH_EXCEPTION_LOCATION);
36413 node_file >> nnodes;
36416 unsigned dimension;
36417 node_file >> dimension;
36422 throw OomphLibError(
"The dimension must be 2\n",
36423 OOMPH_CURRENT_FUNCTION,
36424 OOMPH_EXCEPTION_LOCATION);
36429 Vector<double> x_node(nnodes);
36430 Vector<double> y_node(nnodes);
36433 unsigned npoint_attributes;
36434 node_file >> npoint_attributes;;
36437 unsigned boundary_markers_flag=0;
36438 node_file >> boundary_markers_flag;
36441 unsigned dummy_node_number;
36443 unsigned dummy_node_attribute;
36445 unsigned dummy_node_boundary;
36449 for(
unsigned i=0;i<nnodes;i++)
36451 node_file>>dummy_node_number;
36452 node_file>>x_node[i];
36453 node_file>>y_node[i];
36454 for(
unsigned j=0;j<npoint_attributes;++j)
36456 node_file>>dummy_node_attribute;
36458 if(boundary_markers_flag)
36460 node_file>>dummy_node_boundary;
36469 std::map<unsigned,Vector<std::pair<unsigned,unsigned> > >
36470 unsorted_boundary_segments;
36475 Vector<unsigned> sorted_boundaries_ids;
36481 std::ifstream poly_file(poly_file_name.c_str(),std::ios_base::in);
36484 if(!poly_file.is_open())
36486 std::string error_msg(
"Failed to open poly file: ");
36487 error_msg +=
"\"" + poly_file_name +
"\".";
36488 throw OomphLibError(error_msg, OOMPH_CURRENT_FUNCTION,
36489 OOMPH_EXCEPTION_LOCATION);
36493 unsigned n_node_poly;
36494 poly_file >> n_node_poly;
36497 poly_file >> dimension;
36500 unsigned attribute_flag;
36501 poly_file >> attribute_flag;
36504 poly_file >> boundary_markers_flag;
36509 for(
unsigned i=0;i<n_node_poly;i++)
36516 for(
unsigned j=0;j<attribute_flag;++j)
36518 poly_file >> dummy;
36521 if(boundary_markers_flag==1)
36528 unsigned read_value;
36531 poly_file >> read_value;
36532 const unsigned nglobal_segments = read_value;
36535 poly_file >> boundary_markers_flag;
36538 unsigned global_segment_number;
36541 std::set<unsigned> nodes_ids;
36544 for(
unsigned i=0;i<nglobal_segments;i++)
36547 unsigned lnode_id=0;
36548 unsigned rnode_id=0;
36550 poly_file >> global_segment_number;
36551 poly_file >> lnode_id;
36552 poly_file >> rnode_id;
36553 nodes_ids.insert(lnode_id);
36554 nodes_ids.insert(rnode_id);
36555 if(boundary_markers_flag)
36557 poly_file >> bnd_id;
36563 unsorted_boundary_segments[bnd_id-1].push_back(
36564 std::make_pair(lnode_id, rnode_id));
36571 const unsigned nsorted_boundaries_ids =
36572 sorted_boundaries_ids.size();
36574 bool boundary_id_found =
false;
36575 for (
unsigned ib = 0; ib < nsorted_boundaries_ids; ib++)
36577 if (sorted_boundaries_ids[ib] == bnd_id - 1)
36579 boundary_id_found =
true;
36585 if (!boundary_id_found)
36587 sorted_boundaries_ids.push_back(bnd_id - 1);
36597 if (nglobal_segments != nodes_ids.size())
36599 std::ostringstream error_message;
36601 <<
"The number of nodes (" << nodes_ids.size() <<
") and segments ("
36602 << nglobal_segments <<
") is different.\nThis may mean that there "
36603 <<
"are internal non-closed boundaries defined in\nthe polyfile. "
36604 <<
"If you need this feature please use the TriangleMeshPoyLine\n"
36605 <<
"and TriangleMeshCurviLine objects to define your domain.\n\n";
36606 throw OomphLibError(error_message.str(),
36607 OOMPH_CURRENT_FUNCTION,
36608 OOMPH_EXCEPTION_LOCATION);
36615 const unsigned nboundary = unsorted_boundary_segments.size();
36618 if (nboundary != this->nboundary())
36620 std::ostringstream error_message;
36622 <<
"The number of boundaries on the mesh (" << this->nboundary()
36623 <<
") is different from the number of\nboundaries read from the "
36624 <<
"polyfiles (" << unsorted_boundary_segments.size() <<
")!!!\n\n\n";
36625 throw OomphLibError(error_message.str(),
36626 OOMPH_CURRENT_FUNCTION,
36627 OOMPH_EXCEPTION_LOCATION);
36633 const unsigned nsorted_boundaries_ids =
36634 sorted_boundaries_ids.size();
36636 if (nsorted_boundaries_ids != this->nboundary())
36638 std::ostringstream error_message;
36640 <<
"The number of boundaries on the mesh (" << this->nboundary()
36641 <<
") is different from the number of\nsorted boundaries ids read "
36642 <<
"from the polyfiles (" << nsorted_boundaries_ids <<
")!!!\n\n\n";
36643 throw OomphLibError(error_message.str(),
36644 OOMPH_CURRENT_FUNCTION,
36645 OOMPH_EXCEPTION_LOCATION);
36650 std::map<unsigned, std::list<unsigned> > sorted_boundary_segments;
36653 std::map<unsigned,Vector<std::pair<unsigned,unsigned> > >::iterator it;
36655 for (it = unsorted_boundary_segments.begin();
36656 it != unsorted_boundary_segments.end();
36661 const unsigned bnd_id = (*it).first;
36662 Vector<std::pair<unsigned, unsigned> > segments_edges = (*it).second;
36665 std::map<std::pair<unsigned, unsigned>,
bool> segment_done;
36666 const unsigned nsegments = segments_edges.size();
36669 std::list<unsigned> sorted_segments;
36672 unsigned left_node_id = segments_edges[0].first;
36673 unsigned right_node_id = segments_edges[0].second;
36676 sorted_segments.push_back(left_node_id);
36677 sorted_segments.push_back(right_node_id);
36680 segment_done[segments_edges[0]] =
true;
36683 unsigned nsorted_segments = 1;
36685 while(nsorted_segments < nsegments)
36687 for (
unsigned i = 1; i < nsegments; i++)
36690 if (!segment_done[segments_edges[i]])
36693 unsigned current_left_node_id = segments_edges[i].first;
36694 unsigned current_right_node_id = segments_edges[i].second;
36698 if (current_left_node_id == right_node_id)
36702 sorted_segments.push_back(current_right_node_id);
36704 nsorted_segments++;
36706 segment_done[segments_edges[i]] =
true;
36708 right_node_id = current_right_node_id;
36712 else if (current_right_node_id == left_node_id)
36716 sorted_segments.push_front(current_left_node_id);
36718 nsorted_segments++;
36720 segment_done[segments_edges[i]] =
true;
36722 left_node_id = current_left_node_id;
36726 else if (current_left_node_id == left_node_id)
36730 sorted_segments.push_front(current_right_node_id);
36732 nsorted_segments++;
36734 segment_done[segments_edges[i]] =
true;
36736 left_node_id = current_right_node_id;
36740 else if (current_right_node_id == right_node_id)
36744 sorted_segments.push_back(current_left_node_id);
36746 nsorted_segments++;
36748 segment_done[segments_edges[i]] =
true;
36750 right_node_id = current_left_node_id;
36758 sorted_boundary_segments[bnd_id] = sorted_segments;
36764 if (sorted_boundary_segments.size() != this->nboundary())
36766 std::ostringstream error_message;
36768 <<
"The number of boundaries on the mesh (" << this->nboundary()
36769 <<
") is different from the number\nof sorted boundaries to create the "
36770 <<
"polylines (" << sorted_boundary_segments.size() <<
")\n\n";
36771 throw OomphLibError(error_message.str(),
36772 OOMPH_CURRENT_FUNCTION,
36773 OOMPH_EXCEPTION_LOCATION);
36779 Vector<TriangleMeshPolyLine*> polylines_pt(nboundary);
36780 unsigned current_polyline = 0;
36783 for (
unsigned ib = 0; ib < nsorted_boundaries_ids; ib++)
36786 const unsigned bnd_id = sorted_boundaries_ids[ib];
36790 Vector<unsigned> nodes_ids;
36791 for (std::list<unsigned>::iterator it_list =
36792 sorted_boundary_segments[bnd_id].begin();
36793 it_list != sorted_boundary_segments[bnd_id].end();
36795 {nodes_ids.push_back((*it_list));}
36798 const unsigned nvertices = nodes_ids.size();
36801 Vector<Vector<double> > vertices(nvertices);
36804 for (
unsigned i = 0; i < nvertices; i++)
36807 vertices[i].resize(2);
36808 vertices[i][0] = x_node[nodes_ids[i]-1];
36809 vertices[i][1] = y_node[nodes_ids[i]-1];
36817 polylines_pt[current_polyline] =
36818 new TriangleMeshPolyLine(vertices, bnd_id);
36821 this->Boundary_curve_section_pt[bnd_id] =
36822 dynamic_cast<TriangleMeshCurveSection*
>(polylines_pt[current_polyline]);
36825 current_polyline++;
36832 unsigned nsorted_polylines = 0;
36835 unsigned npolygons = 0;
36838 Vector<TriangleMeshPolygon*> polygons_pt;
36841 std::map<unsigned, bool> polyline_done;
36842 while(nsorted_polylines < nboundary)
36845 std::list<TriangleMeshCurveSection*> sorted_curve_sections_pt;
36847 unsigned init_poly = 0;
36849 bool found_root_polyline =
false;
36852 for (
unsigned i = 0; i < nboundary; i++)
36854 if (!polyline_done[i])
36858 nsorted_polylines++;
36861 found_root_polyline =
true;
36864 polyline_done[i] =
true;
36866 sorted_curve_sections_pt.push_back(polylines_pt[i]);
36873 if (!found_root_polyline)
36875 std::ostringstream error_message;
36877 <<
"Was not possible to found the root polyline to create polygons\n\n";
36878 throw OomphLibError(error_message.str(),
36879 OOMPH_CURRENT_FUNCTION,
36880 OOMPH_EXCEPTION_LOCATION);
36885 const unsigned bnd_id = polylines_pt[init_poly]->boundary_id();
36887 unsigned left_node_id = sorted_boundary_segments[bnd_id].front();
36888 unsigned right_node_id = sorted_boundary_segments[bnd_id].back();
36891 bool closed_polygon =
false;
36896 for (
unsigned i = init_poly; i < nboundary; i++)
36899 if (!polyline_done[i])
36904 const unsigned cbnd_id = polylines_pt[i]->boundary_id();
36906 unsigned cleft_node_id = sorted_boundary_segments[cbnd_id].front();
36907 unsigned cright_node_id = sorted_boundary_segments[cbnd_id].back();
36911 if (cleft_node_id == right_node_id)
36914 sorted_curve_sections_pt.push_back(polylines_pt[i]);
36916 polyline_done[i] =
true;
36918 right_node_id = cright_node_id;
36920 nsorted_polylines++;
36924 else if (cright_node_id == left_node_id)
36927 sorted_curve_sections_pt.push_front(polylines_pt[i]);
36929 polyline_done[i] =
true;
36931 left_node_id = cleft_node_id;
36933 nsorted_polylines++;
36937 else if (cleft_node_id == left_node_id)
36940 polylines_pt[i]->reverse();
36942 sorted_curve_sections_pt.push_front(polylines_pt[i]);
36944 polyline_done[i] =
true;
36946 left_node_id = cright_node_id;
36948 nsorted_polylines++;
36952 else if (cright_node_id == right_node_id)
36955 polylines_pt[i]->reverse();
36957 sorted_curve_sections_pt.push_back(polylines_pt[i]);
36959 polyline_done[i] =
true;
36961 right_node_id = cleft_node_id;
36963 nsorted_polylines++;
36972 if (left_node_id == right_node_id)
36975 closed_polygon =
true;
36978 }
while(nsorted_polylines < nboundary && !closed_polygon);
36981 if (!closed_polygon)
36983 std::ostringstream error_message;
36985 <<
"It was not possible to create a closed curve, these are the "
36986 <<
"vertices of the already sorted polylines\n\n";
36987 unsigned cpolyline = 0;
36988 for (std::list<TriangleMeshCurveSection*>::iterator it_list =
36989 sorted_curve_sections_pt.begin();
36990 it_list != sorted_curve_sections_pt.end();
36993 error_message <<
"Polyline (" << cpolyline <<
")\n";
36994 TriangleMeshPolyLine *tmp_poly_pt =
36995 dynamic_cast<TriangleMeshPolyLine*
>((*it_list));
36996 const unsigned nvertex = tmp_poly_pt->nvertex();
36997 for (
unsigned v = 0; v < nvertex; v++)
36999 error_message <<
"("<<tmp_poly_pt->vertex_coordinate(v)[0]
37000 <<
", "<<tmp_poly_pt->vertex_coordinate(v)[1]<<
")\n";
37002 error_message <<
"\n";
37005 throw OomphLibError(error_message.str(),
37006 OOMPH_CURRENT_FUNCTION,
37007 OOMPH_EXCEPTION_LOCATION);
37013 Vector<TriangleMeshCurveSection*> tmp_sorted_curve_sections_pt;
37014 for (std::list<TriangleMeshCurveSection*>::iterator it_list =
37015 sorted_curve_sections_pt.begin();
37016 it_list != sorted_curve_sections_pt.end();
37018 {tmp_sorted_curve_sections_pt.push_back((*it_list));}
37021 TriangleMeshPolygon *polygon_pt =
37022 new TriangleMeshPolygon(tmp_sorted_curve_sections_pt);
37025 this->Free_polygon_pt.insert(polygon_pt);
37028 polygons_pt.push_back(polygon_pt);
37041 unsigned index_outer = 0;
37043 for (
unsigned idx_outer = 0; idx_outer < npolygons; idx_outer++)
37046 Vector<Vector<double> > outer_vertex_coordinates;
37050 bool all_inner_inside =
true;
37053 const unsigned nouter_polylines = polygons_pt[idx_outer]->npolyline();
37054 for (
unsigned p = 0; p < nouter_polylines; p++)
37056 TriangleMeshPolyLine* tmp_poly_pt =
37057 polygons_pt[idx_outer]->polyline_pt(p);
37058 const unsigned nvertex = tmp_poly_pt->nvertex();
37059 for (
unsigned v = 0; v < nvertex; v++)
37061 Vector<double> current_vertex = tmp_poly_pt->vertex_coordinate(v);
37062 outer_vertex_coordinates.push_back(current_vertex);
37071 const unsigned ninner_polygons = polygons_pt.size() - 1;
37074 Vector<Vector<Vector<double> > > inner_vertex_coordinates(ninner_polygons);
37076 for (
unsigned i = 0; i <= ninner_polygons; i++)
37078 if (i != idx_outer)
37081 const unsigned ninner_polylines = polygons_pt[i]->npolyline();
37082 for (
unsigned p = 0; p < ninner_polylines; p++)
37084 TriangleMeshPolyLine* tmp_poly_pt = polygons_pt[i]->polyline_pt(p);
37085 const unsigned nvertex = tmp_poly_pt->nvertex();
37086 for (
unsigned v = 0; v < nvertex; v++)
37088 Vector<double> current_vertex = tmp_poly_pt->vertex_coordinate(v);
37091 inner_vertex_coordinates[i].push_back(current_vertex);
37093 else if (i > idx_outer)
37095 inner_vertex_coordinates[i-1].push_back(current_vertex);
37107 for (
unsigned i = 0; i < ninner_polygons; i++)
37111 const unsigned nvertex_internal = inner_vertex_coordinates[i].size();
37112 for (
unsigned v = 0; v < nvertex_internal; v++)
37115 Vector<double> current_point = inner_vertex_coordinates[i][v];
37116 all_inner_inside &=
37117 this->is_point_inside_polygon_helper(outer_vertex_coordinates,
37122 if (!all_inner_inside)
37132 if (!all_inner_inside)
37142 if (all_inner_inside)
37144 index_outer = idx_outer;
37154 if (index_outer != 0)
37156 std::ostringstream warning_message;
37158 <<
"The first set of nodes listed in the input polyfiles does not\n"
37159 <<
"correspond to the outer closed boundary. This may lead to\n"
37160 <<
"problems at the adaptation stage if the holes coordinates\n"
37161 <<
"are no correctly associated to the inner closed boundaries.\n"
37162 <<
"You can check the generated mesh by calling the output() method\n"
37163 <<
"from the mesh object '(problem.mesh_pt()->output(string))'\n\n";
37164 OomphLibWarning(warning_message.str(),
37165 OOMPH_CURRENT_FUNCTION,
37166 OOMPH_EXCEPTION_LOCATION);
37175 this->Outer_boundary_pt.resize(1);
37176 this->Outer_boundary_pt[0] = polygons_pt[index_outer];
37178 this->Internal_polygon_pt.resize(npolygons-1);
37179 for (
unsigned i = 0; i < npolygons; i++)
37181 if (i != index_outer)
37183 if (i < index_outer)
37186 this->Internal_polygon_pt[i] = polygons_pt[i];
37188 else if (i > index_outer)
37191 this->Internal_polygon_pt[i-1] = polygons_pt[i];
37202 Vector<Vector<Vector<double> > > inner_vertex_coordinates(npolygons-1);
37204 for (
unsigned i = 0; i < npolygons-1; i++)
37207 const unsigned ninner_polylines =
37208 this->Internal_polygon_pt[i]->npolyline();
37209 for (
unsigned p = 0; p < ninner_polylines; p++)
37211 TriangleMeshPolyLine* tmp_poly_pt =
37212 this->Internal_polygon_pt[i]->polyline_pt(p);
37215 const unsigned nvertex = tmp_poly_pt->nvertex();
37216 for (
unsigned v = 0; v < nvertex; v++)
37218 Vector<double> current_vertex = tmp_poly_pt->vertex_coordinate(v);
37219 inner_vertex_coordinates[i].push_back(current_vertex);
37228 poly_file >> nholes;
37231 if (npolygons > 1 && (npolygons - 1) != nholes)
37233 std::ostringstream error_message;
37235 <<
"The number of holes (" << nholes <<
") does not correspond "
37236 <<
"with the number\nof internal polygons ("
37237 << npolygons - 1 <<
")\n\n"
37238 <<
"Using polyfiles as input does not currently allows the\n"
37239 <<
"definition of more than one outer polygon\n\n";
37240 throw OomphLibError(error_message.str(),
37241 OOMPH_CURRENT_FUNCTION,
37242 OOMPH_EXCEPTION_LOCATION);
37247 Vector<Vector<double> > hole_coordinates(nholes);
37250 unsigned dummy_hole;
37252 for(
unsigned ihole=0;ihole<nholes;ihole++)
37254 hole_coordinates[ihole].resize(2);
37256 poly_file >> dummy_hole;
37257 poly_file >> hole_coordinates[ihole][0];
37258 poly_file >> hole_coordinates[ihole][1];
37263 Vector<unsigned> index_hole_of_internal_polygon(npolygons-1);
37264 std::map<unsigned, bool> hole_done;
37268 for (
unsigned i = 0; i < npolygons-1; i++)
37271 for (
unsigned h = 0; h < nholes; h++)
37277 Vector<double> current_point = hole_coordinates[h];
37279 const bool hole_in_polygon =
37280 this->is_point_inside_polygon_helper(inner_vertex_coordinates[i],
37284 if (hole_in_polygon)
37287 hole_done[h] =
true;
37290 index_hole_of_internal_polygon[i] = h;
37302 if (hole_done.size() != npolygons-1)
37304 std::ostringstream error_message;
37306 <<
"Not all the holes were associated to an internal closed boundary\n"
37307 <<
"Only ("<<hole_done.size()<<
") holes were assigned for a total of\n"
37308 <<
"(" << npolygons-1 <<
") internal closed boundaries.\n"
37309 <<
"You can check the generated mesh by calling the output() method\n"
37310 <<
"from the mesh object '(problem.mesh_pt()->output(string))'\n\n";
37311 throw OomphLibError(error_message.str(),
37312 OOMPH_CURRENT_FUNCTION,
37313 OOMPH_EXCEPTION_LOCATION);
37318 for (
unsigned ihole = 0; ihole < nholes; ihole++)
37321 const unsigned index_hole = index_hole_of_internal_polygon[ihole];
37326 if (index_hole != ihole)
37328 std::ostringstream error_message;
37330 <<
"The hole vertices coordinates are not listed in the same order\n"
37331 <<
"as the nodes that define the internal closed boundaries.\n"
37332 <<
"This may lead to problems in case that the holes coordinates\n"
37333 <<
"were no properly assigned to the internal closed boundaries.\n"
37334 <<
"You can check the generated mesh by calling the output() method\n"
37335 <<
"from the mesh object '(problem.mesh_pt()->output(string))'\n\n";
37336 throw OomphLibError(error_message.str(),
37337 OOMPH_CURRENT_FUNCTION,
37338 OOMPH_EXCEPTION_LOCATION);
37343 this->Internal_polygon_pt[ihole]->internal_point() =
37344 hole_coordinates[index_hole];
37348 poly_file.ignore(80,
'\n');
37355 std::string regions_info_string;
37358 getline(poly_file, regions_info_string);
37362 if (isdigit(regions_info_string.c_str()[0]))
37364 nregions = std::atoi(regions_info_string.c_str());
37372 std::map<unsigned, Vector<double> > regions_coordinates;
37375 unsigned dummy_region;
37377 unsigned region_id;
37380 for(
unsigned iregion=0;iregion<nregions;iregion++)
37382 Vector<double> tmp_region_coordinates(2);
37384 poly_file >> dummy_region;
37385 poly_file >> tmp_region_coordinates[0];
37386 poly_file >> tmp_region_coordinates[1];
37387 poly_file >> region_id;
37388 regions_coordinates[region_id].resize(2);
37389 regions_coordinates[region_id][0] = tmp_region_coordinates[0];
37390 regions_coordinates[region_id][1] = tmp_region_coordinates[1];
37393 poly_file.ignore(80,
'\n');
37396 if (region_id == 0)
37398 std::ostringstream error_message;
37399 error_message <<
"Please use another region id different from zero.\n"
37400 <<
"It is internally used as the default region number.\n";
37401 throw OomphLibError(error_message.str(),
37402 OOMPH_CURRENT_FUNCTION,
37403 OOMPH_EXCEPTION_LOCATION);
37409 this->Regions_coordinates = regions_coordinates;
37419 template <
class ELEMENT>
37422 const Vector<double> &target_area)
37425 unsigned update_was_performed =
false;
37427 const unsigned nele = this->nelement();
37437 Vector<Mesh*> face_mesh_pt;
37438 get_face_mesh_representation(polygon_pt,face_mesh_pt);
37442 Vector<double> vertex_coord(3);
37443 Vector<double> bound_left(1);
37444 Vector<double> bound_right(1);
37446 unsigned n_polyline = polygon_pt->npolyline();
37449 for(
unsigned p = 0; p < n_polyline; p++)
37457 MeshAsGeomObject* mesh_geom_obj_pt=
new MeshAsGeomObject(face_mesh_pt[p]);
37462 std::set<Vector<double> > vertex_nodes;
37466 Vector<Vector<double> > tmp_vector_vertex_node;
37471 Vector<Vector<double> > vector_vertex_node;
37473 #ifdef OOMPH_HAS_MPI
37479 Vector<std::set<Vector<double> > >sub_vertex_nodes;
37483 Vector<Vector<Vector<double> > >sub_tmp_vector_vertex_node;
37488 Vector<Vector<Vector<double> > > sub_vector_vertex_node;
37493 const unsigned bound = polygon_pt->curve_section_pt(p)->boundary_id();
37496 const unsigned chunk = polygon_pt->curve_section_pt(p)->boundary_chunk();
37503 const unsigned nface_element = face_mesh_pt[p]->nelement();
37507 Vector<FiniteElement*> non_halo_face_element_pt;
37510 std::map<FiniteElement*,unsigned> face_element_index_on_boundary;
37512 for(
unsigned ef=0;ef<nface_element;++ef)
37514 FiniteElement* ele_face_pt = face_mesh_pt[p]->finite_element_pt(ef);
37515 #ifdef OOMPH_HAS_MPI
37517 if (this->is_mesh_distributed() && ele_face_pt->is_halo())
37521 non_halo_face_element_pt.push_back(ele_face_pt);
37522 face_element_index_on_boundary[ele_face_pt] = ef;
37526 const unsigned nnon_halo_face_element = non_halo_face_element_pt.size();
37529 std::map<FiniteElement*,bool> face_element_done;
37532 unsigned nsorted_face_elements = 0;
37534 #ifdef OOMPH_HAS_MPI
37536 unsigned nsub_boundaries = 0;
37537 #endif // #ifdef OOMPH_HAS_MPI
37541 while(nsorted_face_elements < nnon_halo_face_element)
37544 FiniteElement* ele_face_pt = 0;
37546 bool found_initial_face_element =
false;
37549 unsigned iface = 0;
37550 for (iface = 0; iface < nnon_halo_face_element; iface++)
37552 ele_face_pt = non_halo_face_element_pt[iface];
37554 if (!face_element_done[ele_face_pt])
37557 found_initial_face_element =
true;
37559 nsorted_face_elements++;
37566 if (!found_initial_face_element)
37568 std::ostringstream error_message;
37570 <<
"Could not find an initial face element for the current segment\n";
37572 throw OomphLibError(error_message.str(),
37573 "RefineableTriangleMesh::update_polygon_using_elements_area()",
37574 OOMPH_EXCEPTION_LOCATION);
37581 std::set<Vector<double> > local_vertex_nodes;
37585 Vector<Vector<double> > local_tmp_vector_vertex_node;
37589 std::set<Vector<double> > sorted_target_areas;
37593 Vector<double> tmp_sorted_target_areas;
37599 unsigned nnode = ele_face_pt->nnode();
37602 ele_face_pt->node_pt(0)->get_coordinates_on_boundary(bound,bound_left);
37603 vertex_coord[0] = bound_left[0];
37606 for(
unsigned i=0;i<2;i++)
37608 vertex_coord[i+1] = ele_face_pt->node_pt(0)->x(i);
37610 local_vertex_nodes.insert(vertex_coord);
37614 ele_face_pt->node_pt(nnode-1)->
37615 get_coordinates_on_boundary(bound,bound_right);
37616 vertex_coord[0] = bound_right[0];
37619 for(
unsigned i=0;i<2;i++)
37621 vertex_coord[i+1] = ele_face_pt->node_pt(nnode-1)->x(i);
37623 local_vertex_nodes.insert(vertex_coord);
37626 Node *first_node_pt = ele_face_pt->node_pt(0);
37627 Node *last_node_pt = ele_face_pt->node_pt(nnode-1);
37630 face_element_done[ele_face_pt] =
true;
37638 Vector<double> zeta_target_area_values(2);
37642 zeta_target_area_values[0] =
37643 std::min(bound_left[0], bound_right[0]);
37646 unsigned ef = face_element_index_on_boundary[ele_face_pt];
37648 FiniteElement *el_pt = this->boundary_element_pt(bound, ef);
37651 bool found_global_element_index =
false;
37653 for (
unsigned eg = 0 ; eg < nele; eg++)
37656 FiniteElement *el_compare_pt = this->finite_element_pt(eg);
37660 if (el_pt == el_compare_pt)
37662 zeta_target_area_values[1] = target_area[eg];
37664 found_global_element_index =
true;
37671 if (!found_global_element_index)
37673 std::ostringstream error_message;
37675 <<
"The global index for the ("<< ef <<
")-th face element "
37676 <<
"on\nthe ("<< bound <<
")-th boundary was not found!!!";
37677 throw OomphLibError(error_message.str(),
37678 "RefineableTriangleMesh::update_polygon_using_elements_area()",
37679 OOMPH_EXCEPTION_LOCATION);
37684 sorted_target_areas.insert(zeta_target_area_values);
37689 bool face_element_added =
false;
37699 for (
unsigned iiface=iface;iiface<nnon_halo_face_element;iiface++)
37701 face_element_added =
false;
37702 ele_face_pt = non_halo_face_element_pt[iiface];
37703 if (!face_element_done[ele_face_pt])
37706 nnode = ele_face_pt->nnode();
37707 Node* left_node_pt = ele_face_pt->node_pt(0);
37708 Node* right_node_pt = ele_face_pt->node_pt(nnode-1);
37710 if (left_node_pt == first_node_pt)
37712 first_node_pt = right_node_pt;
37713 face_element_added =
true;
37715 else if (left_node_pt == last_node_pt)
37717 last_node_pt = right_node_pt;
37718 face_element_added =
true;
37720 else if (right_node_pt == first_node_pt)
37722 first_node_pt = left_node_pt;
37723 face_element_added =
true;
37725 else if (right_node_pt == last_node_pt)
37727 last_node_pt = left_node_pt;
37728 face_element_added =
true;
37731 if (face_element_added)
37735 left_node_pt->get_coordinates_on_boundary(bound,bound_left);
37736 vertex_coord[0] = bound_left[0];
37739 for(
unsigned i=0;i<2;i++)
37741 vertex_coord[i+1] = left_node_pt->x(i);
37743 local_vertex_nodes.insert(vertex_coord);
37747 right_node_pt->get_coordinates_on_boundary(bound,bound_right);
37748 vertex_coord[0] = bound_right[0];
37751 for(
unsigned i=0;i<2;i++)
37753 vertex_coord[i+1] = right_node_pt->x(i);
37755 local_vertex_nodes.insert(vertex_coord);
37759 face_element_done[ele_face_pt] =
true;
37760 nsorted_face_elements++;
37768 zeta_target_area_values[0] =
37769 std::min(bound_left[0], bound_right[0]);
37772 ef = face_element_index_on_boundary[ele_face_pt];
37773 FiniteElement *lel_pt = this->boundary_element_pt(bound, ef);
37776 found_global_element_index =
false;
37778 for (
unsigned eg = 0 ; eg < nele; eg++)
37781 FiniteElement *lel_compare_pt = this->finite_element_pt(eg);
37785 if (lel_pt == lel_compare_pt)
37787 zeta_target_area_values[1] = target_area[eg];
37789 found_global_element_index =
true;
37796 if (!found_global_element_index)
37798 std::ostringstream error_message;
37800 <<
"The global index for the ("<< ef <<
")-th face element "
37801 <<
"on\nthe ("<< bound <<
")-th boundary was not found!!!";
37802 throw OomphLibError(error_message.str(),
37803 "RefineableTriangleMesh::update_polygon_using_elements_area()",
37804 OOMPH_EXCEPTION_LOCATION);
37809 sorted_target_areas.insert(zeta_target_area_values);
37816 }
while(face_element_added &&
37817 (nsorted_face_elements < nnon_halo_face_element));
37825 const unsigned nlocal_nodes = local_vertex_nodes.size();
37827 local_tmp_vector_vertex_node.resize(nlocal_nodes);
37830 unsigned counter = 0;
37831 std::set<Vector<double> >::iterator it_vertex;
37832 for (it_vertex = local_vertex_nodes.begin();
37833 it_vertex != local_vertex_nodes.end();
37836 local_tmp_vector_vertex_node[counter].resize(3);
37837 local_tmp_vector_vertex_node[counter][0] = (*it_vertex)[0];
37838 local_tmp_vector_vertex_node[counter][1] = (*it_vertex)[1];
37839 local_tmp_vector_vertex_node[counter][2] = (*it_vertex)[2];
37845 const unsigned ntarget_areas = sorted_target_areas.size();
37846 tmp_sorted_target_areas.resize(ntarget_areas);
37848 std::set<Vector<double> >::iterator it_area;
37849 for(it_area = sorted_target_areas.begin();
37850 it_area != sorted_target_areas.end();
37853 tmp_sorted_target_areas[counter] = (*it_area)[1];
37858 if (nlocal_nodes > 0 && (ntarget_areas != nlocal_nodes - 1) )
37860 std::ostringstream error_message;
37862 <<
"The boundary (" << bound <<
") was split during the "
37863 <<
"distribution process.\n"
37864 <<
"The problem is in the association of the target areas with the\n"
37865 <<
"elements that gave rise to the vertex coordinates.\n"
37866 <<
"The number of local nodes (" << nlocal_nodes
37867 <<
"), on the 'sub-polyline', is not\n"
37868 <<
"according with the number of target "
37869 <<
"areas ("<< ntarget_areas <<
")\nfor that number of nodes.\n"
37870 <<
"The target areas number MUST be equal to the number of\n"
37871 <<
"local nodes minus one\n\n";
37872 throw OomphLibError(error_message.str(),
37873 OOMPH_CURRENT_FUNCTION,
37874 OOMPH_EXCEPTION_LOCATION);
37885 double unrefinement_tolerance=
37886 polygon_pt->polyline_pt(p)->unrefinement_tolerance();
37889 bool unrefinement_applied =
37890 unrefine_boundary_constrained_by_target_area(
37891 bound, chunk, local_tmp_vector_vertex_node,
37892 unrefinement_tolerance, tmp_sorted_target_areas);
37895 double refinement_tolerance=
37896 polygon_pt->polyline_pt(p)->refinement_tolerance();
37899 bool refinement_applied =
37900 refine_boundary_constrained_by_target_area(
37901 mesh_geom_obj_pt, local_tmp_vector_vertex_node,
37902 refinement_tolerance, tmp_sorted_target_areas);
37906 local_vertex_nodes.clear();
37911 unsigned nnew_nodes = local_tmp_vector_vertex_node.size();
37912 for (
unsigned i = 0; i < nnew_nodes; i++)
37914 vertex_coord[0] = local_tmp_vector_vertex_node[i][0];
37915 vertex_coord[1] = local_tmp_vector_vertex_node[i][1];
37916 vertex_coord[2] = local_tmp_vector_vertex_node[i][2];
37917 vertex_nodes.insert(vertex_coord);
37918 local_vertex_nodes.insert(vertex_coord);
37923 update_was_performed = (unrefinement_applied || refinement_applied);
37925 #ifdef OOMPH_HAS_MPI
37926 if (this->is_mesh_distributed())
37930 sub_vertex_nodes.push_back(local_vertex_nodes);
37939 unsigned npoly_vertex = vertex_nodes.size();
37942 tmp_vector_vertex_node.resize(npoly_vertex);
37943 unsigned count = 0;
37944 for(std::set<Vector<double> >::iterator it = vertex_nodes.begin();
37945 it!=vertex_nodes.end(); ++it)
37947 tmp_vector_vertex_node[count].resize(3);
37948 tmp_vector_vertex_node[count][0] = (*it)[0];
37949 tmp_vector_vertex_node[count][1] = (*it)[1];
37950 tmp_vector_vertex_node[count][2] = (*it)[2];
37954 #ifdef OOMPH_HAS_MPI
37957 unsigned nsub_boundaries_set = sub_vertex_nodes.size();
37958 if (nsub_boundaries_set != nsub_boundaries)
37960 std::ostringstream error_message;
37962 <<
"The number of found sub-boundaries and the number of counted\n"
37963 <<
"sub-boundaries are different:\n"
37964 <<
"Number of found sub-boundaries: ("<<nsub_boundaries_set<<
")\n"
37965 <<
"Number of counted sub-boundaries: ("<<nsub_boundaries<<
")\n";
37966 throw OomphLibError(error_message.str(),
37967 OOMPH_CURRENT_FUNCTION,
37968 OOMPH_EXCEPTION_LOCATION);
37973 if (this->is_mesh_distributed() && nsub_boundaries > 1)
37976 this->Boundary_was_splitted[bound] =
true;
37978 sub_tmp_vector_vertex_node.resize(nsub_boundaries);
37979 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
37982 const unsigned nsubpoly_vertex = sub_vertex_nodes[isub].size();
37983 sub_tmp_vector_vertex_node[isub].resize(nsubpoly_vertex);
37984 unsigned subcount = 0;
37985 std::set<Vector<double> >::iterator subit;
37986 for(subit = sub_vertex_nodes[isub].begin();
37987 subit != sub_vertex_nodes[isub].end(); ++subit)
37989 sub_tmp_vector_vertex_node[isub][subcount].resize(3);
37990 sub_tmp_vector_vertex_node[isub][subcount][0] = (*subit)[0];
37991 sub_tmp_vector_vertex_node[isub][subcount][1] = (*subit)[1];
37992 sub_tmp_vector_vertex_node[isub][subcount][2] = (*subit)[2];
37998 #endif // OOMPH_HAS_MPI
38002 unsigned n_vertex=tmp_vector_vertex_node.size();
38005 vector_vertex_node.resize(n_vertex);
38006 for(
unsigned i=0;i<n_vertex;i++)
38008 vector_vertex_node[i].resize(2);
38009 vector_vertex_node[i][0]=tmp_vector_vertex_node[i][1];
38010 vector_vertex_node[i][1]=tmp_vector_vertex_node[i][2];
38013 #ifdef OOMPH_HAS_MPI
38016 if (this->is_mesh_distributed() && nsub_boundaries > 1)
38021 sub_vector_vertex_node.resize(nsub_boundaries);
38022 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
38024 const unsigned subn_vertex =
38025 sub_tmp_vector_vertex_node[isub].size();
38027 sub_vector_vertex_node[isub].resize(subn_vertex);
38028 for(
unsigned i=0;i<subn_vertex;i++)
38030 sub_vector_vertex_node[isub][i].resize(2);
38031 sub_vector_vertex_node[isub][i][0]=
38032 sub_tmp_vector_vertex_node[isub][i][1];
38033 sub_vector_vertex_node[isub][i][1]=
38034 sub_tmp_vector_vertex_node[isub][i][2];
38044 #endif // OOMPH_HAS_MPI
38049 #ifdef OOMPH_HAS_MPI
38053 if (!this->is_mesh_distributed())
38059 Vector<double> final_vertex_of_previous_segment;
38060 unsigned n_prev_vertex =
38061 polygon_pt->curve_section_pt(p-1)->nvertex();
38062 final_vertex_of_previous_segment =
38063 polygon_pt->polyline_pt(p-1)->
38064 vertex_coordinate(n_prev_vertex-1);
38066 unsigned prev_seg_boundary_id =
38067 polygon_pt->curve_section_pt(p-1)->boundary_id();
38071 double error = 0.0;
38072 for(
unsigned i=0;i<2;i++)
38074 const double dist =
38075 final_vertex_of_previous_segment[i] -
38076 (*vector_vertex_node.begin())[i];
38077 error += dist*dist;
38079 error = sqrt(error);
38083 if(error > ToleranceForVertexMismatchInPolygons::Tolerable_error)
38087 double rev_error = 0.0;
38088 for(
unsigned i=0;i<2;i++)
38090 const double dist =
38091 final_vertex_of_previous_segment[i] -
38092 (*--vector_vertex_node.end())[i];
38093 rev_error += dist*dist;
38095 rev_error = sqrt(rev_error);
38098 ToleranceForVertexMismatchInPolygons::Tolerable_error)
38107 Vector<double> initial_vertex_of_previous_segment;
38109 initial_vertex_of_previous_segment =
38110 polygon_pt->polyline_pt(p-1)->
38111 vertex_coordinate(0);
38113 unsigned prev_seg_boundary_id =
38114 polygon_pt->curve_section_pt(p-1)->boundary_id();
38118 double error = 0.0;
38119 for(
unsigned i=0;i<2;i++)
38121 const double dist =
38122 initial_vertex_of_previous_segment[i] -
38123 (*vector_vertex_node.begin())[i];
38124 error += dist*dist;
38126 error = sqrt(error);
38130 if(error > ToleranceForVertexMismatchInPolygons::Tolerable_error)
38134 double rev_error = 0.0;
38135 for(
unsigned i=0;i<2;i++)
38137 const double dist =
38138 initial_vertex_of_previous_segment[i] -
38139 (*--vector_vertex_node.end())[i];
38140 rev_error += dist*dist;
38142 rev_error = sqrt(rev_error);
38146 ToleranceForVertexMismatchInPolygons::Tolerable_error)
38148 std::ostringstream error_stream;
38150 <<
"The distance between the first node of the current\n"
38151 <<
"line segment (boundary "<<bound<<
") and either end of "
38152 <<
"the previous line segment\n"
38153 <<
"(boundary "<<prev_seg_boundary_id<<
") is bigger than "
38154 <<
"the desired tolerance "
38155 << ToleranceForVertexMismatchInPolygons::Tolerable_error
38157 <<
"This suggests that the polylines defining the "
38159 <<
"representation are not properly ordered.\n"
38160 <<
"Fail on last vertex of polyline: ("
38161 << prev_seg_boundary_id <<
") and\n"
38162 <<
"first vertex of polyline (" << bound <<
").\n"
38163 <<
"This should have failed when first trying to "
38164 <<
"construct the\npolygon.\n";
38165 throw OomphLibError(error_stream.str(),
38166 OOMPH_CURRENT_FUNCTION,
38167 OOMPH_EXCEPTION_LOCATION);
38174 std::reverse(vector_vertex_node.begin(),
38175 vector_vertex_node.end());
38177 polygon_pt->polyline_pt(p-1)->reverse();
38183 polygon_pt->polyline_pt(p-1)->reverse();
38189 std::ostringstream error_stream;
38191 <<
"The distance between the first node of the current\n"
38192 <<
"line segment (boundary " << bound <<
") and either end of "
38193 <<
"the previous line segment\n"
38194 <<
"(boundary "<<prev_seg_boundary_id<<
") is bigger than the "
38195 <<
"desired tolerance " <<
38196 ToleranceForVertexMismatchInPolygons::Tolerable_error <<
".\n"
38197 <<
"This suggests that the polylines defining the polygonal\n"
38198 <<
"representation are not properly ordered.\n"
38199 <<
"Fail on last vertex of polyline: ("<<prev_seg_boundary_id
38200 <<
") and\nfirst vertex of polyline ("<<bound <<
").\n"
38201 <<
"This should have failed when first trying to construct"
38202 <<
" the polygon.\n";
38203 throw OomphLibError(error_stream.str(),
38204 OOMPH_CURRENT_FUNCTION,
38205 OOMPH_EXCEPTION_LOCATION);
38211 std::reverse(vector_vertex_node.begin(),vector_vertex_node.end());
38229 n_vertex = vector_vertex_node.size();
38232 TriangleMeshPolyLine *tmp_polyline_pt =
38233 new TriangleMeshPolyLine(vector_vertex_node,bound);
38237 TriangleMeshCurveSection *tmp_curve_section_pt = tmp_polyline_pt;
38241 double unrefinement_tolerance=
38242 polygon_pt->polyline_pt(p)->unrefinement_tolerance();
38245 double refinement_tolerance=
38246 polygon_pt->polyline_pt(p)->refinement_tolerance();
38249 tmp_polyline_pt->set_unrefinement_tolerance(unrefinement_tolerance);
38250 tmp_polyline_pt->set_refinement_tolerance(refinement_tolerance);
38253 double maximum_length = polygon_pt->polyline_pt(p)->maximum_length();
38254 tmp_polyline_pt->set_maximum_length(maximum_length);
38256 #ifdef OOMPH_HAS_MPI
38259 if (this->is_mesh_distributed())
38265 this->copy_connection_information(polygon_pt->polyline_pt(p),
38266 tmp_curve_section_pt);
38274 this->copy_connection_information(polygon_pt->polyline_pt(p),
38275 tmp_curve_section_pt);
38281 bool delete_it_on_destructor =
false;
38283 std::set<TriangleMeshCurveSection*>::iterator it =
38284 this->Free_curve_section_pt.find(polygon_pt->curve_section_pt(p));
38286 if (it!=this->Free_curve_section_pt.end())
38288 this->Free_curve_section_pt.erase(it);
38289 delete polygon_pt->curve_section_pt(p);
38290 delete_it_on_destructor =
true;
38295 polygon_pt->curve_section_pt(p) = tmp_polyline_pt;
38298 this->Boundary_curve_section_pt[bound] = polygon_pt->curve_section_pt(p);
38300 if (delete_it_on_destructor)
38302 this->Free_curve_section_pt.insert(polygon_pt->curve_section_pt(p));
38305 #ifdef OOMPH_HAS_MPI
38308 if (this->is_mesh_distributed() && nsub_boundaries > 1)
38314 this->Boundary_subpolylines[bound].clear();
38317 this->Boundary_subpolylines[bound].resize(nsub_boundaries);
38318 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
38321 TriangleMeshPolyLine *sub_tmp_polyline_pt =
38322 new TriangleMeshPolyLine(sub_vector_vertex_node[isub], bound, isub);
38326 this->Boundary_subpolylines[bound][isub] = sub_tmp_polyline_pt;
38338 #endif // OOMPH_HAS_MPI
38342 delete mesh_geom_obj_pt;
38347 for(
unsigned p=0;p<n_polyline;p++)
38349 face_mesh_pt[p]->flush_node_storage();
38350 delete face_mesh_pt[p];
38353 return update_was_performed;
38361 template <
class ELEMENT>
38364 const Vector<double> &target_area)
38367 unsigned update_was_performed =
false;
38369 const unsigned nele = this->nelement();
38379 Vector<Mesh*> face_mesh_pt;
38380 get_face_mesh_representation(open_curve_pt,face_mesh_pt);
38384 Vector<double> vertex_coord(3);
38385 Vector<double> bound_left(1);
38386 Vector<double> bound_right(1);
38388 const unsigned ncurve_section = open_curve_pt->ncurve_section();
38391 for(
unsigned cs = 0; cs < ncurve_section; cs++)
38399 MeshAsGeomObject* mesh_geom_obj_pt=
new MeshAsGeomObject(face_mesh_pt[cs]);
38402 const unsigned bound =
38403 open_curve_pt->curve_section_pt(cs)->boundary_id();
38406 const unsigned chunk =
38407 open_curve_pt->curve_section_pt(cs)->boundary_chunk();
38416 const unsigned nface_element = face_mesh_pt[cs]->nelement();
38421 Vector<FiniteElement*> non_halo_doubled_face_element_pt;
38424 std::map<FiniteElement*,unsigned> face_element_index_on_boundary;
38427 std::map<FiniteElement*,bool> face_element_done;
38429 for(
unsigned ef = 0; ef < nface_element; ++ef)
38431 FiniteElement* ele_face_pt = face_mesh_pt[cs]->finite_element_pt(ef);
38436 #ifdef OOMPH_HAS_MPI
38437 if (this->is_mesh_distributed())
38440 if (ele_face_pt->is_halo()) {
continue;}
38445 if (!face_element_done[ele_face_pt])
38450 non_halo_doubled_face_element_pt.push_back(ele_face_pt);
38452 face_element_index_on_boundary[ele_face_pt] = ef;
38454 face_element_done[ele_face_pt] =
true;
38456 const unsigned nnodes = ele_face_pt->nnode();
38459 Node* left_node_pt = ele_face_pt->node_pt(0);
38460 Node* right_node_pt = ele_face_pt->node_pt(nnodes-1);
38464 bool found_other_side_face_ele =
false;
38466 for (
unsigned iface = 0; iface < nface_element; iface++)
38469 FiniteElement *cele_face_pt =
38470 face_mesh_pt[cs]->finite_element_pt(iface);
38472 if (!face_element_done[cele_face_pt])
38474 Node* cleft_node_pt = cele_face_pt->node_pt(0);
38475 Node* cright_node_pt = cele_face_pt->node_pt(nnodes-1);
38477 if ((left_node_pt == cleft_node_pt &&
38478 right_node_pt == cright_node_pt) ||
38479 (left_node_pt == cright_node_pt &&
38480 right_node_pt == cleft_node_pt))
38483 non_halo_doubled_face_element_pt.push_back(cele_face_pt);
38485 face_element_done[cele_face_pt] =
true;
38487 face_element_index_on_boundary[cele_face_pt] = iface;
38490 found_other_side_face_ele =
true;
38498 if (!found_other_side_face_ele)
38500 std::ostringstream error_message;
38502 <<
"The face element at the other side of the boundary ("
38503 << bound <<
") was not found!!\n"
38504 <<
"These are the nodes of the face element:\n"
38505 <<
"("<<left_node_pt->x(0)<<
", "<<left_node_pt->x(1)<<
") "
38506 <<
"and ("<<right_node_pt->x(0)<<
","<<right_node_pt->x(1)<<
")\n\n";
38507 throw OomphLibError(error_message.str(),
38508 "RefineableTriangleMesh::update_open_curve_using_elements_area()",
38509 OOMPH_EXCEPTION_LOCATION);
38518 face_element_done.clear();
38523 std::set<Vector<double> > vertex_nodes;
38527 Vector<Vector<double> > tmp_vector_vertex_node;
38532 Vector<Vector<double> > vector_vertex_node;
38534 #ifdef OOMPH_HAS_MPI
38539 std::vector<bool> internal_to_shared_boundary;
38546 Vector<std::set<Vector<double> > > sub_vertex_nodes;
38550 Vector<Vector<Vector<double> > > sub_tmp_vector_vertex_node;
38555 Vector<Vector<Vector<double> > > sub_vector_vertex_node;
38559 #endif // #ifdef OOMPH_HAS_MPI
38566 unsigned nsorted_face_elements = 0;
38568 #ifdef OOMPH_HAS_MPI
38570 unsigned nsub_boundaries = 0;
38571 #endif // #ifdef OOMPH_HAS_MPI
38574 const unsigned nnon_halo_doubled_face_ele =
38575 non_halo_doubled_face_element_pt.size();
38579 while(nsorted_face_elements < nnon_halo_doubled_face_ele)
38582 FiniteElement* ele_face_pt = 0;
38583 FiniteElement* repeated_ele_face_pt = 0;
38585 bool found_initial_face_element =
false;
38591 bool both_root_face_elements_are_nonhalo =
false;
38593 unsigned iface = 0;
38594 for (iface = 0; iface < nnon_halo_doubled_face_ele; iface+=2)
38596 ele_face_pt = non_halo_doubled_face_element_pt[iface];
38598 if (!face_element_done[ele_face_pt])
38601 face_element_done[ele_face_pt] =
true;
38603 repeated_ele_face_pt = non_halo_doubled_face_element_pt[iface+1];
38605 face_element_done[repeated_ele_face_pt] =
true;
38607 #ifdef OOMPH_HAS_MPI
38608 if (!repeated_ele_face_pt->is_halo())
38609 {both_root_face_elements_are_nonhalo =
true;}
38610 #endif // #ifdef OOMPH_HAS_MPI
38614 nsorted_face_elements+=2;
38618 found_initial_face_element =
true;
38625 if (!found_initial_face_element)
38627 std::ostringstream error_message;
38629 <<
"Could not find an initial face element for the current segment\n";
38630 throw OomphLibError(error_message.str(),
38631 OOMPH_CURRENT_FUNCTION,
38632 OOMPH_EXCEPTION_LOCATION);
38639 std::set<Vector<double> > local_vertex_nodes;
38643 Vector<Vector<double> > local_tmp_vector_vertex_node;
38647 std::set<Vector<double> > sorted_target_areas;
38651 Vector<double> tmp_sorted_target_areas;
38657 const unsigned nnode = ele_face_pt->nnode();
38660 ele_face_pt->node_pt(0)->get_coordinates_on_boundary(bound,bound_left);
38661 vertex_coord[0] = bound_left[0];
38664 for(
unsigned i=0;i<2;i++)
38666 vertex_coord[i+1] = ele_face_pt->node_pt(0)->x(i);
38668 local_vertex_nodes.insert(vertex_coord);
38672 ele_face_pt->node_pt(nnode-1)->get_coordinates_on_boundary(bound,
38674 vertex_coord[0] = bound_right[0];
38677 for(
unsigned i=0;i<2;i++)
38679 vertex_coord[i+1] = ele_face_pt->node_pt(nnode-1)->x(i);
38681 local_vertex_nodes.insert(vertex_coord);
38684 Node *first_node_pt = ele_face_pt->node_pt(0);
38685 Node *last_node_pt = ele_face_pt->node_pt(nnode-1);
38693 Vector<double> zeta_target_area_values(2);
38697 zeta_target_area_values[0] = std::min(bound_left[0], bound_right[0]);
38700 const unsigned ef = face_element_index_on_boundary[ele_face_pt];
38702 FiniteElement *el_pt = this->boundary_element_pt(bound, ef);
38703 double target_area_face_element = 0.0;
38706 bool found_global_element_index =
false;
38708 for (
unsigned eg = 0 ; eg < nele; eg++)
38711 FiniteElement *el_compare_pt = this->finite_element_pt(eg);
38715 if (el_pt == el_compare_pt)
38717 target_area_face_element = target_area[eg];
38719 found_global_element_index =
true;
38726 if (!found_global_element_index)
38728 std::ostringstream error_message;
38730 <<
"The global index for the ("<< ef <<
")-th face element "
38731 <<
"on\nthe ("<< bound <<
")-th boundary was not found!!!";
38732 throw OomphLibError(error_message.str(),
38733 OOMPH_CURRENT_FUNCTION,
38734 OOMPH_EXCEPTION_LOCATION);
38739 const unsigned ref = face_element_index_on_boundary[repeated_ele_face_pt];
38740 FiniteElement *rel_pt = this->boundary_element_pt(bound, ref);
38741 double target_area_repeated_face_element = 0.0;
38744 bool found_global_repeated_element_index =
false;
38746 for (
unsigned eg = 0 ; eg < nele; eg++)
38749 FiniteElement *el_compare_pt = this->finite_element_pt(eg);
38753 if (rel_pt == el_compare_pt)
38755 target_area_repeated_face_element = target_area[eg];
38757 found_global_repeated_element_index =
true;
38764 if (!found_global_repeated_element_index)
38766 std::ostringstream error_message;
38768 <<
"The global index for the ("<< ref <<
")-th face element "
38769 <<
"on\nthe ("<< bound <<
")-th boundary was not found (repeated "
38770 <<
"face element)!!!";
38771 throw OomphLibError(error_message.str(),
38772 OOMPH_CURRENT_FUNCTION,
38773 OOMPH_EXCEPTION_LOCATION);
38779 zeta_target_area_values[1]=std::min(target_area_face_element,
38780 target_area_repeated_face_element);
38783 sorted_target_areas.insert(zeta_target_area_values);
38788 bool face_element_added =
false;
38798 for (
unsigned iiface=iface;
38799 iiface<nnon_halo_doubled_face_ele;iiface+=2)
38801 face_element_added =
false;
38802 ele_face_pt = non_halo_doubled_face_element_pt[iiface];
38809 repeated_ele_face_pt = non_halo_doubled_face_element_pt[iiface+1];
38810 bool both_face_elements_are_nonhalo =
false;
38812 #ifdef OOMPH_HAS_MPI
38813 if (!repeated_ele_face_pt->is_halo())
38814 {both_face_elements_are_nonhalo =
true;}
38815 #endif // #ifdef OOMPH_HAS_MPI
38817 if (!face_element_done[ele_face_pt] &&
38818 (both_face_elements_are_nonhalo ==
38819 both_root_face_elements_are_nonhalo))
38822 const unsigned nlnode = ele_face_pt->nnode();
38823 Node* left_node_pt = ele_face_pt->node_pt(0);
38824 Node* right_node_pt = ele_face_pt->node_pt(nlnode-1);
38826 if (left_node_pt == first_node_pt)
38828 first_node_pt = right_node_pt;
38829 face_element_added =
true;
38831 else if (left_node_pt == last_node_pt)
38833 last_node_pt = right_node_pt;
38834 face_element_added =
true;
38836 else if (right_node_pt == first_node_pt)
38838 first_node_pt = left_node_pt;
38839 face_element_added =
true;
38841 else if (right_node_pt == last_node_pt)
38843 last_node_pt = left_node_pt;
38844 face_element_added =
true;
38847 if (face_element_added)
38851 left_node_pt->get_coordinates_on_boundary(bound,bound_left);
38852 vertex_coord[0] = bound_left[0];
38855 for(
unsigned i=0;i<2;i++)
38857 vertex_coord[i+1] = left_node_pt->x(i);
38859 local_vertex_nodes.insert(vertex_coord);
38863 right_node_pt->get_coordinates_on_boundary(bound,bound_right);
38864 vertex_coord[0] = bound_right[0];
38867 for(
unsigned i=0;i<2;i++)
38869 vertex_coord[i+1] = right_node_pt->x(i);
38871 local_vertex_nodes.insert(vertex_coord);
38875 face_element_done[ele_face_pt] =
true;
38878 repeated_ele_face_pt = non_halo_doubled_face_element_pt[iiface+1];
38879 face_element_done[repeated_ele_face_pt] =
true;
38881 nsorted_face_elements+=2;
38889 zeta_target_area_values[0] =
38890 std::min(bound_left[0], bound_right[0]);
38893 const unsigned lef = face_element_index_on_boundary[ele_face_pt];
38894 FiniteElement *lel_pt = this->boundary_element_pt(bound, lef);
38897 found_global_element_index =
false;
38899 for (
unsigned eg = 0 ; eg < nele; eg++)
38902 FiniteElement *lel_compare_pt = this->finite_element_pt(eg);
38906 if (lel_pt == lel_compare_pt)
38908 target_area_face_element = target_area[eg];
38910 found_global_element_index =
true;
38917 if (!found_global_element_index)
38919 std::ostringstream error_message;
38921 <<
"The global index for the ("<< lef <<
")-th face element "
38922 <<
"on\nthe ("<< bound <<
")-th boundary was not found!!!";
38923 throw OomphLibError(error_message.str(),
38924 OOMPH_CURRENT_FUNCTION,
38925 OOMPH_EXCEPTION_LOCATION);
38930 const unsigned rlef =
38931 face_element_index_on_boundary[repeated_ele_face_pt];
38932 FiniteElement *rlel_pt = this->boundary_element_pt(bound, rlef);
38935 found_global_repeated_element_index =
false;
38937 for (
unsigned eg = 0 ; eg < nele; eg++)
38940 FiniteElement *lel_compare_pt = this->finite_element_pt(eg);
38944 if (rlel_pt == lel_compare_pt)
38946 target_area_repeated_face_element = target_area[eg];
38948 found_global_repeated_element_index =
true;
38955 if (!found_global_repeated_element_index)
38957 std::ostringstream error_message;
38959 <<
"The global index for the ("<< rlef <<
")-th face element "
38960 <<
"on\nthe ("<< bound <<
")-th boundary was not found "
38961 <<
"(repeated face element)!!!";
38962 throw OomphLibError(error_message.str(),
38963 OOMPH_CURRENT_FUNCTION,
38964 OOMPH_EXCEPTION_LOCATION);
38970 zeta_target_area_values[1] =
38971 std::min(target_area_face_element,
38972 target_area_repeated_face_element);
38975 sorted_target_areas.insert(zeta_target_area_values);
38982 }
while(face_element_added &&
38983 (nsorted_face_elements < nnon_halo_doubled_face_ele));
38991 const unsigned nlocal_nodes = local_vertex_nodes.size();
38993 local_tmp_vector_vertex_node.resize(nlocal_nodes);
38996 unsigned counter = 0;
38997 std::set<Vector<double> >::iterator it_vertex;
38998 for (it_vertex = local_vertex_nodes.begin();
38999 it_vertex != local_vertex_nodes.end();
39002 local_tmp_vector_vertex_node[counter].resize(3);
39003 local_tmp_vector_vertex_node[counter][0] = (*it_vertex)[0];
39004 local_tmp_vector_vertex_node[counter][1] = (*it_vertex)[1];
39005 local_tmp_vector_vertex_node[counter][2] = (*it_vertex)[2];
39011 const unsigned ntarget_areas = sorted_target_areas.size();
39012 tmp_sorted_target_areas.resize(ntarget_areas);
39014 std::set<Vector<double> >::iterator it_area;
39015 for(it_area = sorted_target_areas.begin();
39016 it_area != sorted_target_areas.end();
39019 tmp_sorted_target_areas[counter] = (*it_area)[1];
39024 if (nlocal_nodes > 0 && (ntarget_areas != nlocal_nodes - 1) )
39026 std::ostringstream error_message;
39028 <<
"The boundary (" << bound <<
") was split during the "
39029 <<
"distribution process.\n"
39030 <<
"The problem comes when associating the target areas with the "
39031 <<
"elements that gave\nrise to the vertex coordinates.\n"
39032 <<
"The number of local nodes on the 'sub-polyline' ("
39033 << nlocal_nodes <<
") is not according with the number of target\n"
39034 <<
"areas ("<< ntarget_areas <<
") for that number of nodes.\n"
39035 <<
"The target areas number must be equal to the number of nodes-1\n";
39036 throw OomphLibError(error_message.str(),
39037 OOMPH_CURRENT_FUNCTION,
39038 OOMPH_EXCEPTION_LOCATION);
39045 if (local_tmp_vector_vertex_node[nlocal_nodes-1][2] <
39046 local_tmp_vector_vertex_node[0][2])
39048 std::reverse(local_tmp_vector_vertex_node.begin(),
39049 local_tmp_vector_vertex_node.end());
39050 std::reverse(tmp_sorted_target_areas.begin(),
39051 tmp_sorted_target_areas.end());
39053 else if (local_tmp_vector_vertex_node[nlocal_nodes-1][2] ==
39054 local_tmp_vector_vertex_node[0][2])
39056 if (local_tmp_vector_vertex_node[nlocal_nodes-1][1] <
39057 local_tmp_vector_vertex_node[0][1])
39059 std::reverse(local_tmp_vector_vertex_node.begin(),
39060 local_tmp_vector_vertex_node.end());
39061 std::reverse(tmp_sorted_target_areas.begin(),
39062 tmp_sorted_target_areas.end());
39073 double unrefinement_tolerance=
39074 open_curve_pt->polyline_pt(cs)->unrefinement_tolerance();
39077 bool unrefinement_applied =
39078 unrefine_boundary_constrained_by_target_area(
39079 bound, chunk, local_tmp_vector_vertex_node,
39080 unrefinement_tolerance, tmp_sorted_target_areas);
39083 double refinement_tolerance=
39084 open_curve_pt->polyline_pt(cs)->refinement_tolerance();
39087 bool refinement_applied =
39088 refine_boundary_constrained_by_target_area(
39089 mesh_geom_obj_pt, local_tmp_vector_vertex_node,
39090 refinement_tolerance, tmp_sorted_target_areas);
39094 local_vertex_nodes.clear();
39099 const unsigned nnew_nodes = local_tmp_vector_vertex_node.size();
39100 for (
unsigned i = 0; i < nnew_nodes; i++)
39102 vertex_coord[0] = local_tmp_vector_vertex_node[i][0];
39103 vertex_coord[1] = local_tmp_vector_vertex_node[i][1];
39104 vertex_coord[2] = local_tmp_vector_vertex_node[i][2];
39105 vertex_nodes.insert(vertex_coord);
39106 local_vertex_nodes.insert(vertex_coord);
39111 update_was_performed = (unrefinement_applied || refinement_applied);
39113 #ifdef OOMPH_HAS_MPI
39114 if (this->is_mesh_distributed())
39119 sub_vertex_nodes.push_back(local_vertex_nodes);
39125 if (both_root_face_elements_are_nonhalo)
39126 {internal_to_shared_boundary.push_back(
false);}
39128 {internal_to_shared_boundary.push_back(
true);}
39138 const unsigned npoly_vertex = vertex_nodes.size();
39139 tmp_vector_vertex_node.resize(npoly_vertex);
39140 unsigned count = 0;
39141 for (std::set<Vector<double> >::iterator it = vertex_nodes.begin();
39142 it!=vertex_nodes.end(); ++it)
39144 tmp_vector_vertex_node[count].resize(3);
39145 tmp_vector_vertex_node[count][0] = (*it)[0];
39146 tmp_vector_vertex_node[count][1] = (*it)[1];
39147 tmp_vector_vertex_node[count][2] = (*it)[2];
39151 #ifdef OOMPH_HAS_MPI
39156 const unsigned nsub_boundaries_set = sub_vertex_nodes.size();
39157 const unsigned ninternal_to_shared_boundaries =
39158 internal_to_shared_boundary.size();
39159 if (nsub_boundaries_set != ninternal_to_shared_boundaries)
39161 std::ostringstream error_message;
39163 <<
"The number of found sub-boundaries and the number of marked "
39164 <<
"internal\nboundaries are different\n"
39165 <<
"Number of found sub-boundaries: ("<<nsub_boundaries_set<<
")\n"
39166 <<
"Number of marked internal boundaries: ("
39167 << ninternal_to_shared_boundaries <<
")\n\n";
39168 throw OomphLibError(error_message.str(),
39169 OOMPH_CURRENT_FUNCTION,
39170 OOMPH_EXCEPTION_LOCATION);
39176 if (nsub_boundaries_set != nsub_boundaries)
39178 std::ostringstream error_message;
39180 <<
"The number of found sub-boundaries and the number of counted\n"
39181 <<
"sub-boundaries are different:\n"
39182 <<
"Number of found sub-boundaries: ("<<nsub_boundaries_set<<
")\n"
39183 <<
"Number of counted sub-boundaries: ("<<nsub_boundaries<<
")\n\n";
39184 throw OomphLibError(error_message.str(),
39185 OOMPH_CURRENT_FUNCTION,
39186 OOMPH_EXCEPTION_LOCATION);
39191 if (this->is_mesh_distributed() && nsub_boundaries > 1)
39194 this->Boundary_was_splitted[bound] =
true;
39197 sub_tmp_vector_vertex_node.resize(nsub_boundaries);
39199 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
39202 const unsigned nsubpoly_vertex = sub_vertex_nodes[isub].size();
39203 sub_tmp_vector_vertex_node[isub].resize(nsubpoly_vertex);
39204 unsigned subcount = 0;
39205 std::set<Vector<double> >::iterator subit;
39206 for(subit = sub_vertex_nodes[isub].begin();
39207 subit != sub_vertex_nodes[isub].end(); ++subit)
39209 sub_tmp_vector_vertex_node[isub][subcount].resize(3);
39210 sub_tmp_vector_vertex_node[isub][subcount][0] = (*subit)[0];
39211 sub_tmp_vector_vertex_node[isub][subcount][1] = (*subit)[1];
39212 sub_tmp_vector_vertex_node[isub][subcount][2] = (*subit)[2];
39218 #endif // OOMPH_HAS_MPI
39222 unsigned n_vertex=tmp_vector_vertex_node.size();
39225 vector_vertex_node.resize(n_vertex);
39226 for(
unsigned i=0;i<n_vertex;i++)
39228 vector_vertex_node[i].resize(2);
39229 vector_vertex_node[i][0]=tmp_vector_vertex_node[i][1];
39230 vector_vertex_node[i][1]=tmp_vector_vertex_node[i][2];
39233 #ifdef OOMPH_HAS_MPI
39236 if (this->is_mesh_distributed() && nsub_boundaries > 1)
39241 sub_vector_vertex_node.resize(nsub_boundaries);
39242 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
39244 const unsigned subn_vertex =
39245 sub_tmp_vector_vertex_node[isub].size();
39247 sub_vector_vertex_node[isub].resize(subn_vertex);
39248 for(
unsigned i=0;i<subn_vertex;i++)
39250 sub_vector_vertex_node[isub][i].resize(2);
39251 sub_vector_vertex_node[isub][i][0]=
39252 sub_tmp_vector_vertex_node[isub][i][1];
39253 sub_vector_vertex_node[isub][i][1]=
39254 sub_tmp_vector_vertex_node[isub][i][2];
39264 #endif // OOMPH_HAS_MPI
39269 #ifdef OOMPH_HAS_MPI
39273 if (!this->is_mesh_distributed())
39279 Vector<double> final_vertex_of_previous_segment;
39280 unsigned n_prev_vertex =
39281 open_curve_pt->curve_section_pt(cs-1)->nvertex();
39282 final_vertex_of_previous_segment =
39283 open_curve_pt->polyline_pt(cs-1)->
39284 vertex_coordinate(n_prev_vertex-1);
39286 unsigned prev_seg_boundary_id =
39287 open_curve_pt->curve_section_pt(cs-1)->boundary_id();
39291 double error = 0.0;
39292 for(
unsigned i=0;i<2;i++)
39294 const double dist =
39295 final_vertex_of_previous_segment[i] -
39296 (*vector_vertex_node.begin())[i];
39297 error += dist*dist;
39299 error = sqrt(error);
39303 if(error > ToleranceForVertexMismatchInPolygons::Tolerable_error)
39307 double rev_error = 0.0;
39308 for(
unsigned i=0;i<2;i++)
39310 const double dist =
39311 final_vertex_of_previous_segment[i] -
39312 (*--vector_vertex_node.end())[i];
39313 rev_error += dist*dist;
39315 rev_error = sqrt(rev_error);
39318 ToleranceForVertexMismatchInPolygons::Tolerable_error)
39327 Vector<double> initial_vertex_of_previous_segment;
39329 initial_vertex_of_previous_segment =
39330 open_curve_pt->polyline_pt(cs-1)->vertex_coordinate(0);
39332 unsigned prev_seg_boundary_id =
39333 open_curve_pt->curve_section_pt(cs-1)->boundary_id();
39337 double error = 0.0;
39338 for(
unsigned i=0;i<2;i++)
39340 const double dist =
39341 initial_vertex_of_previous_segment[i] -
39342 (*vector_vertex_node.begin())[i];
39343 error += dist*dist;
39345 error = sqrt(error);
39349 if(error > ToleranceForVertexMismatchInPolygons::Tolerable_error)
39353 double rev_error = 0.0;
39354 for(
unsigned i=0;i<2;i++)
39356 const double dist =
39357 initial_vertex_of_previous_segment[i] -
39358 (*--vector_vertex_node.end())[i];
39359 rev_error += dist*dist;
39361 rev_error = sqrt(rev_error);
39365 ToleranceForVertexMismatchInPolygons::Tolerable_error)
39367 std::ostringstream error_stream;
39369 <<
"The distance between the first node of the current\n"
39370 <<
"line segment (boundary "<<bound<<
") and either end of "
39371 <<
"the previous line segment\n"
39372 <<
"(boundary "<<prev_seg_boundary_id<<
") is bigger than"
39373 <<
" the desired tolerance " <<
39374 ToleranceForVertexMismatchInPolygons::Tolerable_error<<
".\n"
39375 <<
"This suggests that the polylines defining the polygonal\n"
39376 <<
"representation are not properly ordered.\n"
39377 <<
"Fail on last vertex of polyline: ("
39378 <<prev_seg_boundary_id<<
") and\nfirst vertex of polyline ("
39379 <<bound<<
").\nThis should have failed when first trying to "
39380 <<
"construct the\npolygon.\n";
39381 throw OomphLibError(error_stream.str(),
39382 OOMPH_CURRENT_FUNCTION,
39383 OOMPH_EXCEPTION_LOCATION);
39389 std::reverse(vector_vertex_node.begin(),
39390 vector_vertex_node.end());
39391 open_curve_pt->polyline_pt(cs-1)->reverse();
39397 open_curve_pt->polyline_pt(cs-1)->reverse();
39403 std::ostringstream error_stream;
39405 <<
"The distance between the first node of the current\n"
39406 <<
"line segment (boundary " << bound <<
") and either end of "
39407 <<
"the previous line segment\n"
39408 <<
"(boundary "<<prev_seg_boundary_id<<
") is bigger than the "
39409 <<
"desired tolerance " <<
39410 ToleranceForVertexMismatchInPolygons::Tolerable_error <<
".\n"
39411 <<
"This suggests that the polylines defining the polygonal\n"
39412 <<
"representation are not properly ordered.\n"
39413 <<
"Fail on last vertex of polyline: ("<<prev_seg_boundary_id
39414 <<
") and\nfirst vertex of polyline (" <<bound <<
").\n"
39415 <<
"This should have failed when first trying to construct\n"
39416 <<
"the polygon.\n";
39417 throw OomphLibError(error_stream.str(),
39418 OOMPH_CURRENT_FUNCTION,
39419 OOMPH_EXCEPTION_LOCATION);
39425 std::reverse(vector_vertex_node.begin(),vector_vertex_node.end());
39443 n_vertex = vector_vertex_node.size();
39446 TriangleMeshPolyLine *tmp_polyline_pt =
39447 new TriangleMeshPolyLine(vector_vertex_node,bound);
39451 TriangleMeshCurveSection *tmp_curve_section_pt = tmp_polyline_pt;
39455 double unrefinement_tolerance=
39456 open_curve_pt->polyline_pt(cs)->unrefinement_tolerance();
39459 double refinement_tolerance=
39460 open_curve_pt->polyline_pt(cs)->refinement_tolerance();
39463 tmp_polyline_pt->set_unrefinement_tolerance(unrefinement_tolerance);
39464 tmp_polyline_pt->set_refinement_tolerance(refinement_tolerance);
39467 double maximum_length = open_curve_pt->polyline_pt(cs)->maximum_length();
39468 tmp_polyline_pt->set_maximum_length(maximum_length);
39470 #ifdef OOMPH_HAS_MPI
39473 if (this->is_mesh_distributed())
39479 this->copy_connection_information(open_curve_pt->polyline_pt(cs),
39480 tmp_curve_section_pt);
39488 this->copy_connection_information(open_curve_pt->polyline_pt(cs),
39489 tmp_curve_section_pt);
39495 bool delete_it_on_destructor =
false;
39497 std::set<TriangleMeshCurveSection*>::iterator it =
39498 this->Free_curve_section_pt.find(open_curve_pt->curve_section_pt(cs));
39500 if (it!=this->Free_curve_section_pt.end())
39502 this->Free_curve_section_pt.erase(it);
39503 delete open_curve_pt->curve_section_pt(cs);
39504 delete_it_on_destructor =
true;
39509 open_curve_pt->curve_section_pt(cs) = tmp_polyline_pt;
39512 this->Boundary_curve_section_pt[bound] =
39513 open_curve_pt->curve_section_pt(cs);
39515 if (delete_it_on_destructor)
39517 this->Free_curve_section_pt.insert(open_curve_pt->curve_section_pt(cs));
39520 #ifdef OOMPH_HAS_MPI
39523 if (this->is_mesh_distributed() && nsub_boundaries == 1)
39526 this->Boundary_marked_as_shared_boundary[bound].clear();
39529 this->Boundary_marked_as_shared_boundary[bound].push_back(
39530 internal_to_shared_boundary[0]);
39534 else if (this->is_mesh_distributed() && nsub_boundaries > 1)
39540 this->Boundary_subpolylines[bound].clear();
39542 this->Boundary_subpolylines[bound].resize(nsub_boundaries);
39545 this->Boundary_marked_as_shared_boundary[bound].clear();
39548 this->Boundary_marked_as_shared_boundary[bound].resize(nsub_boundaries);
39549 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
39553 TriangleMeshPolyLine *sub_tmp_polyline_pt =
39554 new TriangleMeshPolyLine(sub_vector_vertex_node[isub], bound, isub);
39558 this->Boundary_subpolylines[bound][isub] = sub_tmp_polyline_pt;
39562 this->Boundary_marked_as_shared_boundary[bound][isub] =
39563 internal_to_shared_boundary[isub];
39572 TriangleMeshCurveSection *tmp_sub_curve_section_pt =
39573 sub_tmp_polyline_pt;
39574 this->copy_connection_information_to_sub_polylines(
39575 tmp_curve_section_pt, tmp_sub_curve_section_pt);
39581 #endif // OOMPH_HAS_MPI
39585 delete mesh_geom_obj_pt;
39590 for(
unsigned p = 0; p < ncurve_section; p++)
39592 face_mesh_pt[p]->flush_node_storage();
39593 delete face_mesh_pt[p];
39596 return update_was_performed;
39600 #ifdef OOMPH_HAS_MPI
39605 template <
class ELEMENT>
39608 &vector_polyline_pt,
39609 const Vector<double> &target_areas)
39613 unsigned update_was_performed =
false;
39616 const unsigned n_polylines = vector_polyline_pt.size();
39617 for (
unsigned pp = 0; pp < n_polylines; pp++)
39620 const unsigned shd_bnd_id = vector_polyline_pt[pp]->boundary_id();
39623 const unsigned chunk = vector_polyline_pt[pp]->boundary_chunk();
39631 std::map<FiniteElement*, FiniteElement*> face_ele_pt_to_bulk_element_pt;
39634 Vector<FiniteElement*> halo_shared_face_ele_pt;
39636 Vector<FiniteElement*> nonhalo_shared_face_ele_pt;
39640 const unsigned nshared_bound_ele =
39641 this->nshared_boundary_element(shd_bnd_id);
39645 for (
unsigned e = 0; e < nshared_bound_ele; e++)
39648 FiniteElement* bulk_ele_pt =
39649 this->shared_boundary_element_pt(shd_bnd_id, e);
39652 int face_index = this->face_index_at_shared_boundary(shd_bnd_id, e);
39656 FiniteElement* face_ele_pt =
39657 new DummyFaceElement<ELEMENT>(bulk_ele_pt, face_index);
39661 face_ele_pt_to_bulk_element_pt[face_ele_pt] = bulk_ele_pt;
39664 if (!bulk_ele_pt->is_halo())
39667 nonhalo_shared_face_ele_pt.push_back(face_ele_pt);
39672 halo_shared_face_ele_pt.push_back(face_ele_pt);
39679 Vector<Vector<FiniteElement*> > unsorted_shared_bulk_ele_pt;
39682 std::map<FiniteElement*, bool> shared_face_done;
39685 const unsigned nnonhalo_face_shared_ele =
39686 nonhalo_shared_face_ele_pt.size();
39689 const unsigned nhalo_face_shared_ele =
39690 halo_shared_face_ele_pt.size();
39695 if (nshared_bound_ele / 2 != nnonhalo_face_shared_ele)
39697 std::ostringstream error_message;
39699 <<
"The number of shared boundary elements (" << nshared_bound_ele
39700 <<
") is not the double\nof the number of unsorted NONHALO shared "
39701 <<
"face boundary elements (" << nnonhalo_face_shared_ele <<
")\n"
39702 <<
"for the current boundary ("<< shd_bnd_id <<
")\n\n";
39703 throw OomphLibError(error_message.str(),
39704 OOMPH_CURRENT_FUNCTION,
39705 OOMPH_EXCEPTION_LOCATION);
39710 if (nshared_bound_ele / 2 != nhalo_face_shared_ele)
39712 std::ostringstream error_message;
39714 <<
"The number of shared boundary elements (" << nshared_bound_ele
39715 <<
") is not the double\nof the number of unsorted HALO shared "
39716 <<
"face boundary elements (" << nhalo_face_shared_ele <<
")\n"
39717 <<
"for the current boundary ("<< shd_bnd_id <<
")\n\n";
39718 throw OomphLibError(error_message.str(),
39719 OOMPH_CURRENT_FUNCTION,
39720 OOMPH_EXCEPTION_LOCATION);
39727 for (
unsigned inh = 0; inh < nnonhalo_face_shared_ele; inh++)
39730 FiniteElement* nonhalo_face_ele_pt = nonhalo_shared_face_ele_pt[inh];
39733 const unsigned nnodes_nh = nonhalo_face_ele_pt->nnode();
39735 Node* nh_first_node_pt = nonhalo_face_ele_pt->node_pt(0);
39736 Node* nh_last_node_pt = nonhalo_face_ele_pt->node_pt(nnodes_nh-1);
39740 for (
unsigned ih = 0; ih < nhalo_face_shared_ele; ih++)
39743 FiniteElement* halo_face_ele_pt = halo_shared_face_ele_pt[ih];
39746 if (!shared_face_done[halo_face_ele_pt])
39749 const unsigned nnodes_h = halo_face_ele_pt->nnode();
39751 Node* h_first_node_pt = halo_face_ele_pt->node_pt(0);
39752 Node* h_last_node_pt = halo_face_ele_pt->node_pt(nnodes_h-1);
39756 if (nh_first_node_pt == h_first_node_pt &&
39757 nh_last_node_pt == h_last_node_pt)
39760 Vector<FiniteElement*> tmp_bulk_element_pt;
39763 FiniteElement* nonhalo_bulk_ele_pt =
39764 face_ele_pt_to_bulk_element_pt[nonhalo_face_ele_pt];
39765 FiniteElement* halo_bulk_ele_pt =
39766 face_ele_pt_to_bulk_element_pt[halo_face_ele_pt];
39769 tmp_bulk_element_pt.push_back(nonhalo_bulk_ele_pt);
39770 tmp_bulk_element_pt.push_back(halo_bulk_ele_pt);
39773 unsorted_shared_bulk_ele_pt.push_back(tmp_bulk_element_pt);
39776 shared_face_done[nonhalo_face_ele_pt] =
true;
39777 shared_face_done[halo_face_ele_pt] =
true;
39783 else if (nh_first_node_pt == h_last_node_pt &&
39784 nh_last_node_pt == h_first_node_pt)
39787 Vector<FiniteElement*> tmp_bulk_element_pt;
39790 FiniteElement* nonhalo_bulk_ele_pt =
39791 face_ele_pt_to_bulk_element_pt[nonhalo_face_ele_pt];
39792 FiniteElement* halo_bulk_ele_pt =
39793 face_ele_pt_to_bulk_element_pt[halo_face_ele_pt];
39796 tmp_bulk_element_pt.push_back(nonhalo_bulk_ele_pt);
39797 tmp_bulk_element_pt.push_back(halo_bulk_ele_pt);
39800 unsorted_shared_bulk_ele_pt.push_back(tmp_bulk_element_pt);
39803 shared_face_done[nonhalo_face_ele_pt] =
true;
39804 shared_face_done[halo_face_ele_pt] =
true;
39826 const unsigned nunsorted_shared_bulk_ele =
39827 unsorted_shared_bulk_ele_pt.size();
39831 if (nshared_bound_ele / 2 != nunsorted_shared_bulk_ele)
39833 std::ostringstream error_message;
39835 <<
"The number of shared boundary elements (" << nshared_bound_ele
39836 <<
") is not the double\nof the number of unsorted shared bulk "
39837 <<
"boundary elements (" << nunsorted_shared_bulk_ele <<
")\n"
39838 <<
"for the current boundary ("<< shd_bnd_id <<
")\n\n";
39839 throw OomphLibError(error_message.str(),
39840 OOMPH_CURRENT_FUNCTION,
39841 OOMPH_EXCEPTION_LOCATION);
39846 if ((nnonhalo_face_shared_ele + nhalo_face_shared_ele) !=
39847 shared_face_done.size())
39849 std::ostringstream error_message;
39851 <<
"The number of DONE shared boundary face elements ("
39852 << shared_face_done.size() <<
") is not the same\n as the sum of"
39853 <<
"the nonhalo face shared boundary elements ("
39854 << nnonhalo_face_shared_ele <<
")\nand the halo face shared "
39855 <<
"boundary elements ("<< nhalo_face_shared_ele <<
") for the\n/"
39856 <<
"current boundary (" << shd_bnd_id <<
")\n\n";
39857 throw OomphLibError(error_message.str(),
39858 OOMPH_CURRENT_FUNCTION,
39859 OOMPH_EXCEPTION_LOCATION);
39864 shared_face_done.clear();
39867 unsigned nsorted_face_ele = 0;
39871 std::list<Node*> sorted_nodes;
39874 std::list<FiniteElement*> sorted_shared_bound_elements_pt;
39877 FiniteElement* root_face_ele_pt = nonhalo_shared_face_ele_pt[0];
39878 nsorted_face_ele++;
39881 shared_face_done[root_face_ele_pt] =
true;
39884 const unsigned nnodes_root = root_face_ele_pt->nnode();
39885 Node *first_node_pt = root_face_ele_pt->node_pt(0);
39886 Node *last_node_pt = root_face_ele_pt->node_pt(nnodes_root-1);
39889 sorted_nodes.push_back(first_node_pt);
39890 sorted_nodes.push_back(last_node_pt);
39893 sorted_shared_bound_elements_pt.push_back(
39894 unsorted_shared_bulk_ele_pt[0][0]);
39895 sorted_shared_bound_elements_pt.push_back(
39896 unsorted_shared_bulk_ele_pt[0][1]);
39899 while (nsorted_face_ele < nnonhalo_face_shared_ele)
39902 bool node_added =
false;
39906 for (
unsigned iface = 1; iface < nnonhalo_face_shared_ele; iface++)
39908 FiniteElement* tmp_shared_face_ele_pt =
39909 nonhalo_shared_face_ele_pt[iface];
39912 if (!shared_face_done[tmp_shared_face_ele_pt])
39915 const unsigned tmp_nnodes = tmp_shared_face_ele_pt->nnode();
39918 Node* left_node_pt = tmp_shared_face_ele_pt->node_pt(0);
39919 Node* right_node_pt = tmp_shared_face_ele_pt->node_pt(tmp_nnodes-1);
39921 if (left_node_pt == first_node_pt)
39924 sorted_nodes.push_front(right_node_pt);
39925 first_node_pt = right_node_pt;
39929 sorted_shared_bound_elements_pt.push_front(
39930 unsorted_shared_bulk_ele_pt[iface][1]);
39931 sorted_shared_bound_elements_pt.push_front(
39932 unsorted_shared_bulk_ele_pt[iface][0]);
39934 else if (left_node_pt == last_node_pt)
39937 sorted_nodes.push_back(right_node_pt);
39938 last_node_pt = right_node_pt;
39942 sorted_shared_bound_elements_pt.push_back(
39943 unsorted_shared_bulk_ele_pt[iface][0]);
39944 sorted_shared_bound_elements_pt.push_back(
39945 unsorted_shared_bulk_ele_pt[iface][1]);
39947 else if (right_node_pt == first_node_pt)
39950 sorted_nodes.push_front(left_node_pt);
39951 first_node_pt = left_node_pt;
39955 sorted_shared_bound_elements_pt.push_front(
39956 unsorted_shared_bulk_ele_pt[iface][1]);
39957 sorted_shared_bound_elements_pt.push_front(
39958 unsorted_shared_bulk_ele_pt[iface][0]);
39960 else if (right_node_pt == last_node_pt)
39963 sorted_nodes.push_back(left_node_pt);
39964 last_node_pt = left_node_pt;
39968 sorted_shared_bound_elements_pt.push_back(
39969 unsorted_shared_bulk_ele_pt[iface][0]);
39970 sorted_shared_bound_elements_pt.push_back(
39971 unsorted_shared_bulk_ele_pt[iface][1]);
39978 shared_face_done[tmp_shared_face_ele_pt] =
true;
39979 nsorted_face_ele++;
39996 for (
unsigned inh = 0; inh < nnonhalo_face_shared_ele; inh++)
39998 delete nonhalo_shared_face_ele_pt[inh];
39999 nonhalo_shared_face_ele_pt[inh] = 0;
40003 for (
unsigned ih = 0; ih < nhalo_face_shared_ele; ih++)
40005 delete halo_shared_face_ele_pt[ih];
40006 halo_shared_face_ele_pt[ih] = 0;
40014 const unsigned n_nodes = sorted_nodes.size();
40017 Vector<Vector<double> > polyline_vertices(n_nodes);
40020 unsigned counter = 0;
40021 for (std::list<Node*>::iterator it_nodes = sorted_nodes.begin();
40022 it_nodes != sorted_nodes.end();
40025 polyline_vertices[counter].resize(2);
40026 polyline_vertices[counter][0] = (*it_nodes)->x(0);
40027 polyline_vertices[counter][1] = (*it_nodes)->x(1);
40036 Vector<FiniteElement*> sorted_shared_ele_pt;
40037 for (std::list<FiniteElement*>::iterator it_ele =
40038 sorted_shared_bound_elements_pt.begin();
40039 it_ele != sorted_shared_bound_elements_pt.end();
40041 {sorted_shared_ele_pt.push_back((*it_ele));}
40044 const unsigned n_shared_target_areas = sorted_shared_ele_pt.size();
40045 Vector<double> sorted_shared_target_areas(n_shared_target_areas);
40048 std::map<std::pair<GeneralisedElement*, unsigned>,
bool> shared_ele_done;
40051 unsigned count_found_shared_element = 0;
40054 const unsigned nele = this->nelement();
40058 for (
unsigned e = 0; e < nele; e++)
40060 GeneralisedElement* current_ele_pt = this->element_pt(e);
40063 for (
unsigned s = 0;
s < n_shared_target_areas;
s++)
40066 GeneralisedElement* current_shared_ele_pt = sorted_shared_ele_pt[
s];
40068 std::pair<GeneralisedElement*, unsigned> pair_gen_ele_idx =
40069 std::make_pair(current_shared_ele_pt,
s);
40070 if (!shared_ele_done[pair_gen_ele_idx])
40073 if (current_ele_pt == current_shared_ele_pt)
40076 sorted_shared_target_areas[
s] = target_areas[e];
40078 shared_ele_done[pair_gen_ele_idx] =
true;
40080 count_found_shared_element++;
40086 if (count_found_shared_element == n_shared_target_areas)
40094 if (count_found_shared_element != n_shared_target_areas)
40096 std::ostringstream error_message;
40098 <<
"The number of found target areas ("
40099 << count_found_shared_element <<
") is different from the "
40100 <<
"total number\nof target areas ("
40101 << n_shared_target_areas <<
") in shared boundary ("
40102 << shd_bnd_id <<
")\n\n";
40103 throw OomphLibError(error_message.str(),
40104 OOMPH_CURRENT_FUNCTION,
40105 OOMPH_EXCEPTION_LOCATION);
40110 const unsigned n_vertices = n_nodes;
40113 const unsigned n_segments = vector_polyline_pt[pp]->nsegment();
40122 if (n_segments != n_vertices-1)
40124 std::ostringstream error_message;
40126 <<
"The number of segments from the current shared polyline "
40127 <<
"(" << n_segments <<
") does not\ncorrespond with the number of "
40128 <<
"sorted vertices (" << n_vertices-1 <<
") of the current shared\n"
40130 throw OomphLibError(error_message.str(),
40131 OOMPH_CURRENT_FUNCTION,
40132 OOMPH_EXCEPTION_LOCATION);
40137 if (n_segments != n_shared_target_areas/2)
40139 std::ostringstream error_message;
40141 <<
"The number of segments for the current sorting of edges "
40142 <<
"(" << n_segments <<
") is different\nfrom the number of "
40143 <<
"target areas (" << n_shared_target_areas/2 <<
")\n\n";
40144 throw OomphLibError(error_message.str(),
40145 OOMPH_CURRENT_FUNCTION,
40146 OOMPH_EXCEPTION_LOCATION);
40158 Vector<double> polyline_target_area(n_segments);
40160 for (
unsigned s = 0;
s < n_segments;
s++)
40163 polyline_target_area[
s] = std::min(sorted_shared_target_areas[
s*2],
40164 sorted_shared_target_areas[(
s*2)+1]);
40171 if (polyline_vertices[n_vertices-1][1] < polyline_vertices[0][1])
40173 std::reverse(polyline_vertices.begin(), polyline_vertices.end());
40174 std::reverse(polyline_target_area.begin(), polyline_target_area.end());
40176 else if (polyline_vertices[n_vertices-1][1] == polyline_vertices[0][1])
40178 if (polyline_vertices[n_vertices-1][0] < polyline_vertices[0][0])
40180 std::reverse(polyline_vertices.begin(), polyline_vertices.end());
40181 std::reverse(polyline_target_area.begin(), polyline_target_area.end());
40187 bool unrefinement_applied =
false;
40190 if (n_vertices > 3)
40192 unrefinement_applied =
40193 unrefine_shared_boundary_constrained_by_target_area(
40194 shd_bnd_id, chunk, polyline_vertices, polyline_target_area);
40198 bool refinement_applied =
40199 refine_shared_boundary_constrained_by_target_area(polyline_vertices,
40200 polyline_target_area);
40203 update_was_performed |= (unrefinement_applied || refinement_applied);
40209 TriangleMeshPolyLine *new_polyline_pt =
40210 new TriangleMeshPolyLine(polyline_vertices, shd_bnd_id);
40213 TriangleMeshCurveSection *curve_section_pt = vector_polyline_pt[pp];
40217 this->copy_connection_information(curve_section_pt, new_polyline_pt);
40222 bool delete_it_on_destructor =
false;
40226 std::set<TriangleMeshCurveSection*>::iterator it =
40227 this->Free_curve_section_pt.find(curve_section_pt);
40229 if (it!=this->Free_curve_section_pt.end())
40231 this->Free_curve_section_pt.erase(it);
40232 delete curve_section_pt;
40233 delete_it_on_destructor =
true;
40237 vector_polyline_pt[pp] = new_polyline_pt;
40240 TriangleMeshCurveSection *new_curve_section_pt = vector_polyline_pt[pp];
40243 this->Boundary_curve_section_pt[shd_bnd_id] = new_curve_section_pt;
40245 if (delete_it_on_destructor)
40247 this->Free_curve_section_pt.insert(new_curve_section_pt);
40252 return update_was_performed;
40255 #endif // #ifdef OOMPH_HAS_MPI
40262 template<
class ELEMENT>
40266 Vector<Vector<double> >
40267 &vector_bnd_vertices,
40268 double &unrefinement_tolerance,
40269 Vector<double> &area_constraint)
40272 std::set<Vector<double> > no_delete_vertex;
40275 const bool boundary_receive_connections =
40276 this->boundary_connections(b, c, no_delete_vertex);
40280 bool unrefinement_applied =
false;
40283 if (!Do_boundary_unrefinement_constrained_by_target_areas)
40285 return unrefinement_applied;
40299 unsigned n_vertex = vector_bnd_vertices.size();
40302 const double constant_value = 4.0/sqrt(3.0);
40308 for (
unsigned i = 1; i < n_vertex-1; i+=2)
40310 if (area_constraint[i-1] > 0 && area_constraint[i] > 0)
40312 const double local_zeta_first = vector_bnd_vertices[i-1][0];
40313 const double local_zeta_last = vector_bnd_vertices[i+1][0];
40314 const double local_length_zeta =
40315 std::fabs(local_zeta_last-local_zeta_first);
40317 const double x1 = vector_bnd_vertices[i-1][1];
40318 const double y1 = vector_bnd_vertices[i-1][2];
40319 const double x2 = vector_bnd_vertices[i+1][1];
40320 const double y2 = vector_bnd_vertices[i+1][2];
40321 const double local_length =
40322 sqrt(((x1-x2)*(x1-x2)) + ((y1-y2)*(y1-y2)));
40324 const double x_m = vector_bnd_vertices[i][1];
40325 const double y_m = vector_bnd_vertices[i][2];
40327 const double average_area_constraint =
40328 (area_constraint[i-1] + area_constraint[i]) / 2.0;
40332 const double length_side =
40333 sqrt(constant_value*average_area_constraint);
40335 const double length_side_zeta =
40336 (local_length_zeta * length_side) / local_length;
40339 if ((length_side_zeta / local_length_zeta) > 1.0)
40346 double a_x=vector_bnd_vertices[i-1][1];
40347 double a_y=vector_bnd_vertices[i-1][2];
40348 double b_x=vector_bnd_vertices[i][1];
40349 double b_y=vector_bnd_vertices[i][2];
40350 double c_x=vector_bnd_vertices[i+1][1];
40351 double c_y=vector_bnd_vertices[i+1][2];
40358 double e=a*(a_x+b_x)+b*(a_y+b_y);
40359 double f=c*(a_x+c_x)+d*(a_y+c_y);
40361 double g=2.0*(a*(c_y-b_y)-b*(c_x-b_x));
40364 if (std::fabs(g)<1.0e-14)
40370 double p_x=(d*e-b*f)/g;
40371 double p_y=(a*f-c*e)/g;
40373 double r=sqrt(pow((a_x-p_x),2)+pow((a_y-p_y),2));
40375 double rhalfca_x=0.5*(a_x-c_x);
40376 double rhalfca_y=0.5*(a_y-c_y);
40378 double halfca_squared=pow(rhalfca_x,2)+pow(rhalfca_y,2);
40380 double sticky_out_bit=r-sqrt(std::fabs((r*r) - halfca_squared));
40385 if ((sticky_out_bit/(2.0*sqrt(halfca_squared)))<
40386 unrefinement_tolerance)
40394 if (do_it && boundary_receive_connections)
40397 for (std::set<Vector<double> >::iterator it =
40398 no_delete_vertex.begin();
40399 it != no_delete_vertex.end(); it++)
40403 const double x = (*it)[0];
40404 const double y = (*it)[1];
40405 double error = (x_m - x)*(x_m - x) + (y_m - y)*(y_m - y);
40406 error = sqrt(error);
40409 ToleranceForVertexMismatchInPolygons::Tolerable_error)
40423 vector_bnd_vertices[i].resize(0);
40431 Vector<Vector<double> > compact_vector;
40434 Vector<double> compact_area_constraint;
40437 for(
unsigned i = 0; i < n_vertex; i++)
40440 if (vector_bnd_vertices[i].size()!=0)
40442 compact_vector.push_back(vector_bnd_vertices[i]);
40448 unsigned nsize_target = area_constraint.size();
40449 if (nsize_target == 1)
40452 compact_area_constraint.push_back(area_constraint[0]);
40456 for(
unsigned i = 1; i < n_vertex; i+=2)
40460 if (vector_bnd_vertices[i].size()!=0)
40462 compact_area_constraint.push_back(area_constraint[i-1]);
40464 if (i < nsize_target)
40466 compact_area_constraint.push_back(area_constraint[i]);
40473 double new_area_constraint =
40474 (area_constraint[i-1] + area_constraint[i]) / 2.0;
40475 compact_area_constraint.push_back(new_area_constraint);
40482 if( n_vertex != compact_vector.size() )
40484 unrefinement_applied =
true;
40488 n_vertex = compact_vector.size();
40489 vector_bnd_vertices.resize(n_vertex);
40490 for(
unsigned i = 0; i < n_vertex; i++)
40492 vector_bnd_vertices[i].resize(3);
40493 vector_bnd_vertices[i][0] = compact_vector[i][0];
40494 vector_bnd_vertices[i][1] = compact_vector[i][1];
40495 vector_bnd_vertices[i][2] = compact_vector[i][2];
40499 unsigned ntarget_areas = compact_area_constraint.size();
40500 area_constraint.resize(ntarget_areas);
40501 for(
unsigned i = 0; i < ntarget_areas; i++)
40503 area_constraint[i] = compact_area_constraint[i];
40508 return unrefinement_applied;
40517 template<
class ELEMENT>
40521 Vector<Vector<double> >
40522 &vector_bnd_vertices,
40523 double &refinement_tolerance,
40524 Vector<double> &area_constraint)
40528 bool refinement_applied =
false;
40531 if (!Do_boundary_refinement_constrained_by_target_areas)
40533 return refinement_applied;
40537 unsigned n_vertex=vector_bnd_vertices.size();
40540 const double constant_value = 4.0/sqrt(3.0);
40546 Vector<Vector<double> > new_vector;
40550 for (
unsigned i = 0; i < n_vertex-1; i++)
40553 new_vector.push_back(vector_bnd_vertices[i]);
40555 if (area_constraint[i] > 0)
40557 double local_zeta_first = vector_bnd_vertices[i][0];
40558 double local_zeta_last = vector_bnd_vertices[i+1][0];
40559 const double local_length_zeta =
40560 std::fabs(local_zeta_last-local_zeta_first);
40565 if (local_zeta_first > local_zeta_last)
40567 const double tmp_zeta = local_zeta_first;
40568 local_zeta_first = local_zeta_last;
40569 local_zeta_last = tmp_zeta;
40572 const double x1 = vector_bnd_vertices[i][1];
40573 const double y1 = vector_bnd_vertices[i][2];
40574 const double x2 = vector_bnd_vertices[i+1][1];
40575 const double y2 = vector_bnd_vertices[i+1][2];
40576 const double local_length =
40577 sqrt(((x1-x2)*(x1-x2)) + ((y1-y2)*(y1-y2)));
40580 const double length_side = sqrt(constant_value*area_constraint[i]);
40581 const double length_side_zeta =
40582 (local_length_zeta * length_side) / local_length;
40585 const double n_seg_double = length_side_zeta/local_length_zeta;
40588 unsigned n_seg = 1;
40591 n_seg+=
static_cast<unsigned>(std::floor(1.0/n_seg_double));
40598 double zeta_increment = (local_length_zeta)/((
double)n_seg);
40600 Vector<double> zeta(1);
40602 for(
unsigned s=1;
s<n_seg;
s++)
40605 zeta[0]= local_zeta_first + zeta_increment*double(
s);
40606 Vector<double> vertex(2);
40607 mesh_geom_obj_pt->position(zeta, vertex);
40610 Vector<double> new_node(3);
40611 new_node[0]=zeta[0];
40612 new_node[1]=vertex[0];
40613 new_node[2]=vertex[1];
40616 new_vector.push_back(new_node);
40627 new_vector.push_back(vector_bnd_vertices[n_vertex-1]);
40632 n_vertex=new_vector.size();
40633 if( n_vertex != vector_bnd_vertices.size() )
40635 refinement_applied =
true;
40639 vector_bnd_vertices.resize(n_vertex);
40640 for(
unsigned i=0;i<n_vertex;i++)
40642 vector_bnd_vertices[i].resize(3);
40643 vector_bnd_vertices[i][0]=new_vector[i][0];
40644 vector_bnd_vertices[i][1]=new_vector[i][1];
40645 vector_bnd_vertices[i][2]=new_vector[i][2];
40650 return refinement_applied;
40661 template <
class ELEMENT>
40666 Vector<Vector<double> > &vector_bnd_vertices,
40667 Vector<double> &area_constraint)
40670 std::set<Vector<double> > no_delete_vertex;
40673 const bool boundary_receive_connections =
40674 this->boundary_connections(b, c, no_delete_vertex);
40678 bool unrefinement_applied =
false;
40681 if (!Do_shared_boundary_unrefinement_constrained_by_target_areas)
40683 return unrefinement_applied;
40699 unsigned n_vertex = vector_bnd_vertices.size();
40702 const double constant_value = 4.0/sqrt(3.0);
40708 for (
unsigned i = 1; i < n_vertex-1; i+=2)
40712 if (area_constraint[i-1] > 0 && area_constraint[i] > 0)
40715 const double x1 = vector_bnd_vertices[i-1][0];
40716 const double y1 = vector_bnd_vertices[i-1][1];
40718 const double x2 = vector_bnd_vertices[i+1][0];
40719 const double y2 = vector_bnd_vertices[i+1][1];
40722 const double local_length =
40723 sqrt(((x1-x2)*(x1-x2)) + ((y1-y2)*(y1-y2)));
40726 const double x_m = vector_bnd_vertices[i][0];
40727 const double y_m = vector_bnd_vertices[i][1];
40730 const double average_area_constraint =
40731 (area_constraint[i-1] + area_constraint[i]) / 2.0;
40735 const double length_side =
40736 sqrt(constant_value*average_area_constraint);
40739 if ((length_side / local_length) > 1.0)
40745 if (do_it && boundary_receive_connections)
40748 for (std::set<Vector<double> >::iterator it =
40749 no_delete_vertex.begin();
40750 it != no_delete_vertex.end(); it++)
40754 const double x = (*it)[0];
40755 const double y = (*it)[1];
40756 double error = (x_m - x)*(x_m - x) + (y_m - y)*(y_m - y);
40757 error = sqrt(error);
40760 ToleranceForVertexMismatchInPolygons::Tolerable_error)
40774 vector_bnd_vertices[i].resize(0);
40784 Vector<Vector<double> > compact_vector;
40787 Vector<double> compact_area_constraint;
40790 for(
unsigned i = 0; i < n_vertex; i++)
40793 if (vector_bnd_vertices[i].size()!=0)
40795 compact_vector.push_back(vector_bnd_vertices[i]);
40801 unsigned n_area_constraint = area_constraint.size();
40802 if (n_area_constraint == 1)
40805 compact_area_constraint.push_back(area_constraint[0]);
40809 for(
unsigned i = 1; i < n_vertex; i+=2)
40813 if (vector_bnd_vertices[i].size()!=0)
40815 compact_area_constraint.push_back(area_constraint[i-1]);
40817 if (i < n_area_constraint)
40819 compact_area_constraint.push_back(area_constraint[i]);
40826 const double new_area_constraint =
40827 (area_constraint[i-1] + area_constraint[i]) / 2.0;
40828 compact_area_constraint.push_back(new_area_constraint);
40835 if( n_vertex != compact_vector.size() )
40837 unrefinement_applied =
true;
40841 n_vertex = compact_vector.size();
40842 vector_bnd_vertices.resize(n_vertex);
40843 for(
unsigned i = 0; i < n_vertex; i++)
40845 vector_bnd_vertices[i].resize(2);
40846 vector_bnd_vertices[i][0] = compact_vector[i][0];
40847 vector_bnd_vertices[i][1] = compact_vector[i][1];
40851 unsigned ntarget_areas = compact_area_constraint.size();
40852 area_constraint.resize(ntarget_areas);
40853 for(
unsigned i = 0; i < ntarget_areas; i++)
40855 area_constraint[i] = compact_area_constraint[i];
40860 return unrefinement_applied;
40871 template <
class ELEMENT>
40874 Vector<Vector<double> > &vector_bnd_vertices,
40875 Vector<double> &area_constraint)
40879 bool refinement_applied =
false;
40882 if (!Do_shared_boundary_refinement_constrained_by_target_areas)
40884 return refinement_applied;
40888 unsigned nsegments = vector_bnd_vertices.size() - 1;
40892 Vector<Vector<double> > tmp_bnd_vertices;
40895 const double constant_value = 4.0/sqrt(3.0);
40897 for (
unsigned s = 0;
s < nsegments;
s++)
40899 Vector<double> left_vertex = vector_bnd_vertices[
s];
40900 Vector<double> right_vertex = vector_bnd_vertices[
s+1];
40903 const double x1 = left_vertex[0];
40904 const double y1 = left_vertex[1];
40905 const double x2 = right_vertex[0];
40906 const double y2 = right_vertex[1];
40909 const double segment_length =
40910 sqrt(((x1-x2)*(x1-x2))+((y1-y2)*(y1-y2)));
40913 const double new_segment_length =
40914 sqrt(constant_value*area_constraint[
s]);
40917 const double n_seg_double = new_segment_length / segment_length;
40922 nseg+=
static_cast<unsigned>(std::floor(1.0/n_seg_double));
40926 tmp_bnd_vertices.push_back(left_vertex);
40933 double incrementx = (right_vertex[0] - left_vertex[0])/(
double)(nseg);
40934 double incrementy = (right_vertex[1] - left_vertex[1])/(
double)(nseg);
40935 for (
unsigned i = 1; i < nseg; i++)
40937 Vector<double> tmp_vertex(2);
40938 tmp_vertex[0] = left_vertex[0] + incrementx*i;
40939 tmp_vertex[1] = left_vertex[1] + incrementy*i;
40940 tmp_bnd_vertices.push_back(tmp_vertex);
40948 tmp_bnd_vertices.push_back(vector_bnd_vertices[nsegments]);
40953 nsegments = tmp_bnd_vertices.size() - 1;
40954 if( nsegments != vector_bnd_vertices.size() - 1 )
40956 refinement_applied =
true;
40959 vector_bnd_vertices.resize(nsegments + 1);
40960 for(
unsigned i = 0; i < nsegments + 1; i++)
40962 vector_bnd_vertices[i].resize(2);
40963 vector_bnd_vertices[i][0] = tmp_bnd_vertices[i][0];
40964 vector_bnd_vertices[i][1] = tmp_bnd_vertices[i][1];
40968 return refinement_applied;
40975 template <
class ELEMENT>
40986 Vector<Mesh*> face_mesh_pt;
40987 get_face_mesh_representation(polygon_pt,face_mesh_pt);
40991 Vector<double> vertex_coord(3);
40992 Vector<double> bound_left(1);
40993 Vector<double> bound_right(1);
40995 const unsigned n_polyline = polygon_pt->npolyline();
40998 for(
unsigned p=0;p<n_polyline;p++)
41006 MeshAsGeomObject* mesh_geom_obj_pt=
new MeshAsGeomObject(face_mesh_pt[p]);
41011 std::set<Vector<double> > vertex_nodes;
41015 Vector<Vector<double> > tmp_vector_vertex_node;
41020 Vector<Vector<double> > vector_vertex_node;
41022 #ifdef OOMPH_HAS_MPI
41028 Vector<std::set<Vector<double> > >sub_vertex_nodes;
41032 Vector<Vector<Vector<double> > >sub_tmp_vector_vertex_node;
41037 Vector<Vector<Vector<double> > > sub_vector_vertex_node;
41042 unsigned bound=polygon_pt->curve_section_pt(p)->boundary_id();
41049 const unsigned nface_element = face_mesh_pt[p]->nelement();
41053 Vector<FiniteElement*> non_halo_face_element_pt;
41055 std::map<FiniteElement*,unsigned> face_element_index_on_boundary;
41057 for(
unsigned ef=0;ef<nface_element;++ef)
41059 FiniteElement* ele_face_pt = face_mesh_pt[p]->finite_element_pt(ef);
41061 #ifdef OOMPH_HAS_MPI
41062 if (this->is_mesh_distributed())
41065 if (ele_face_pt->is_halo()) {
continue;}
41069 non_halo_face_element_pt.push_back(ele_face_pt);
41070 face_element_index_on_boundary[ele_face_pt] = ef;
41074 const unsigned nnon_halo_face_element = non_halo_face_element_pt.size();
41077 std::map<FiniteElement*,bool> face_element_done;
41080 unsigned nsorted_face_elements = 0;
41082 #ifdef OOMPH_HAS_MPI
41084 unsigned nsub_boundaries = 0;
41085 #endif // #ifdef OOMPH_HAS_MPI
41089 while(nsorted_face_elements < nnon_halo_face_element)
41092 FiniteElement* ele_face_pt = 0;
41094 bool found_initial_face_element =
false;
41097 unsigned iface = 0;
41098 for (iface = 0; iface < nnon_halo_face_element; iface++)
41100 ele_face_pt = non_halo_face_element_pt[iface];
41102 if (!face_element_done[ele_face_pt])
41105 found_initial_face_element =
true;
41107 nsorted_face_elements++;
41114 if (!found_initial_face_element)
41116 std::ostringstream error_message;
41118 <<
"Could not find an initial face element for the current segment\n";
41120 throw OomphLibError(error_message.str(),
41121 "RefineableTriangleMesh::update_polygon_after_restart()",
41122 OOMPH_EXCEPTION_LOCATION);
41129 std::set<Vector<double> > local_vertex_nodes;
41133 Vector<Vector<double> > local_tmp_vector_vertex_node;
41141 unsigned nnode = ele_face_pt->nnode();
41144 ele_face_pt->node_pt(0)->get_coordinates_on_boundary(bound,bound_left);
41145 vertex_coord[0] = bound_left[0];
41148 for(
unsigned i=0;i<2;i++)
41150 vertex_coord[i+1] = ele_face_pt->node_pt(0)->x(i);
41152 local_vertex_nodes.insert(vertex_coord);
41156 ele_face_pt->node_pt(nnode-1)->
41157 get_coordinates_on_boundary(bound,bound_right);
41158 vertex_coord[0] = bound_right[0];
41161 for(
unsigned i=0;i<2;i++)
41163 vertex_coord[i+1] = ele_face_pt->node_pt(nnode-1)->x(i);
41165 local_vertex_nodes.insert(vertex_coord);
41168 Node *first_node_pt = ele_face_pt->node_pt(0);
41169 Node *last_node_pt = ele_face_pt->node_pt(nnode-1);
41172 face_element_done[ele_face_pt] =
true;
41180 bool face_element_added =
false;
41189 for (
unsigned iiface=iface;iiface<nnon_halo_face_element;iiface++)
41191 face_element_added =
false;
41192 ele_face_pt = non_halo_face_element_pt[iiface];
41193 if (!face_element_done[ele_face_pt])
41196 nnode = ele_face_pt->nnode();
41197 Node* left_node_pt = ele_face_pt->node_pt(0);
41198 Node* right_node_pt = ele_face_pt->node_pt(nnode-1);
41200 if (left_node_pt == first_node_pt)
41202 first_node_pt = right_node_pt;
41203 face_element_added =
true;
41205 else if (left_node_pt == last_node_pt)
41207 last_node_pt = right_node_pt;
41208 face_element_added =
true;
41210 else if (right_node_pt == first_node_pt)
41212 first_node_pt = left_node_pt;
41213 face_element_added =
true;
41215 else if (right_node_pt == last_node_pt)
41217 last_node_pt = left_node_pt;
41218 face_element_added =
true;
41221 if (face_element_added)
41225 left_node_pt->get_coordinates_on_boundary(bound,bound_left);
41226 vertex_coord[0] = bound_left[0];
41229 for(
unsigned i=0;i<2;i++)
41231 vertex_coord[i+1] = left_node_pt->x(i);
41233 local_vertex_nodes.insert(vertex_coord);
41237 right_node_pt->get_coordinates_on_boundary(bound,bound_right);
41238 vertex_coord[0] = bound_right[0];
41241 for(
unsigned i=0;i<2;i++)
41243 vertex_coord[i+1] = right_node_pt->x(i);
41245 local_vertex_nodes.insert(vertex_coord);
41249 face_element_done[ele_face_pt] =
true;
41250 nsorted_face_elements++;
41257 }
while(face_element_added &&
41258 (nsorted_face_elements < nnon_halo_face_element));
41266 const unsigned nlocal_nodes = local_vertex_nodes.size();
41268 local_tmp_vector_vertex_node.resize(nlocal_nodes);
41271 unsigned counter = 0;
41272 std::set<Vector<double> >::iterator it_vertex;
41273 for (it_vertex = local_vertex_nodes.begin();
41274 it_vertex != local_vertex_nodes.end();
41277 local_tmp_vector_vertex_node[counter].resize(3);
41278 local_tmp_vector_vertex_node[counter][0] = (*it_vertex)[0];
41279 local_tmp_vector_vertex_node[counter][1] = (*it_vertex)[1];
41280 local_tmp_vector_vertex_node[counter][2] = (*it_vertex)[2];
41291 local_vertex_nodes.clear();
41296 unsigned nnew_nodes = local_tmp_vector_vertex_node.size();
41297 for (
unsigned i = 0; i < nnew_nodes; i++)
41299 vertex_coord[0] = local_tmp_vector_vertex_node[i][0];
41300 vertex_coord[1] = local_tmp_vector_vertex_node[i][1];
41301 vertex_coord[2] = local_tmp_vector_vertex_node[i][2];
41302 vertex_nodes.insert(vertex_coord);
41303 local_vertex_nodes.insert(vertex_coord);
41306 #ifdef OOMPH_HAS_MPI
41307 if (this->is_mesh_distributed())
41311 sub_vertex_nodes.push_back(local_vertex_nodes);
41320 unsigned npoly_vertex = vertex_nodes.size();
41321 tmp_vector_vertex_node.resize(npoly_vertex);
41322 unsigned count = 0;
41323 std::set<Vector<double> >::iterator it;
41324 for(it = vertex_nodes.begin(); it!=vertex_nodes.end(); ++it)
41326 tmp_vector_vertex_node[count].resize(3);
41327 tmp_vector_vertex_node[count][0] = (*it)[0];
41328 tmp_vector_vertex_node[count][1] = (*it)[1];
41329 tmp_vector_vertex_node[count][2] = (*it)[2];
41333 #ifdef OOMPH_HAS_MPI
41336 unsigned nsub_boundaries_set = sub_vertex_nodes.size();
41337 if (nsub_boundaries_set != nsub_boundaries)
41339 std::ostringstream error_message;
41341 <<
"The number of found sub-boundaries and the number of counted\n"
41342 <<
"sub-boundaries are different:\n"
41343 <<
"Number of found sub-boundaries: ("<<nsub_boundaries_set<<
")\n"
41344 <<
"Number of counted sub-boundaries: ("<<nsub_boundaries<<
")\n";
41345 throw OomphLibError(error_message.str(),
41346 "RefineableTriangleMesh::update_polygon_after_restart()",
41347 OOMPH_EXCEPTION_LOCATION);
41352 if (this->is_mesh_distributed() && nsub_boundaries > 1)
41355 this->Boundary_was_splitted[bound] =
true;
41357 sub_tmp_vector_vertex_node.resize(nsub_boundaries);
41358 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
41361 const unsigned nsubpoly_vertex = sub_vertex_nodes[isub].size();
41362 sub_tmp_vector_vertex_node[isub].resize(nsubpoly_vertex);
41363 unsigned subcount = 0;
41364 std::set<Vector<double> >::iterator subit;
41365 for(subit = sub_vertex_nodes[isub].begin();
41366 subit != sub_vertex_nodes[isub].end(); ++subit)
41368 sub_tmp_vector_vertex_node[isub][subcount].resize(3);
41369 sub_tmp_vector_vertex_node[isub][subcount][0] = (*subit)[0];
41370 sub_tmp_vector_vertex_node[isub][subcount][1] = (*subit)[1];
41371 sub_tmp_vector_vertex_node[isub][subcount][2] = (*subit)[2];
41377 #endif // OOMPH_HAS_MPI
41382 unsigned n_vertex=tmp_vector_vertex_node.size();
41385 vector_vertex_node.resize(n_vertex);
41386 for(
unsigned i=0;i<n_vertex;i++)
41388 vector_vertex_node[i].resize(2);
41389 vector_vertex_node[i][0]=tmp_vector_vertex_node[i][1];
41390 vector_vertex_node[i][1]=tmp_vector_vertex_node[i][2];
41393 #ifdef OOMPH_HAS_MPI
41396 if (this->is_mesh_distributed() && nsub_boundaries > 1)
41401 sub_vector_vertex_node.resize(nsub_boundaries);
41402 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
41404 const unsigned subn_vertex =
41405 sub_tmp_vector_vertex_node[isub].size();
41407 sub_vector_vertex_node[isub].resize(subn_vertex);
41408 for(
unsigned i=0;i<subn_vertex;i++)
41410 sub_vector_vertex_node[isub][i].resize(2);
41411 sub_vector_vertex_node[isub][i][0]=
41412 sub_tmp_vector_vertex_node[isub][i][1];
41413 sub_vector_vertex_node[isub][i][1]=
41414 sub_tmp_vector_vertex_node[isub][i][2];
41424 #endif // OOMPH_HAS_MPI
41429 #ifdef OOMPH_HAS_MPI
41433 if (!this->is_mesh_distributed())
41439 Vector<double> final_vertex_of_previous_segment;
41440 unsigned n_prev_vertex =
41441 polygon_pt->curve_section_pt(p-1)->nvertex();
41442 final_vertex_of_previous_segment =
41443 polygon_pt->polyline_pt(p-1)->
41444 vertex_coordinate(n_prev_vertex-1);
41446 unsigned prev_seg_boundary_id =
41447 polygon_pt->curve_section_pt(p-1)->boundary_id();
41451 double error = 0.0;
41452 for(
unsigned i=0;i<2;i++)
41454 const double dist =
41455 final_vertex_of_previous_segment[i] -
41456 (*vector_vertex_node.begin())[i];
41457 error += dist*dist;
41459 error = sqrt(error);
41463 if(error > ToleranceForVertexMismatchInPolygons::Tolerable_error)
41467 double rev_error = 0.0;
41468 for(
unsigned i=0;i<2;i++)
41470 const double dist =
41471 final_vertex_of_previous_segment[i] -
41472 (*--vector_vertex_node.end())[i];
41473 rev_error += dist*dist;
41475 rev_error = sqrt(rev_error);
41478 ToleranceForVertexMismatchInPolygons::Tolerable_error)
41487 Vector<double> initial_vertex_of_previous_segment;
41489 initial_vertex_of_previous_segment =
41490 polygon_pt->polyline_pt(p-1)->
41491 vertex_coordinate(0);
41493 unsigned prev_seg_boundary_id =
41494 polygon_pt->curve_section_pt(p-1)->boundary_id();
41498 double error = 0.0;
41499 for(
unsigned i=0;i<2;i++)
41501 const double dist =
41502 initial_vertex_of_previous_segment[i] -
41503 (*vector_vertex_node.begin())[i];
41504 error += dist*dist;
41506 error = sqrt(error);
41510 if(error > ToleranceForVertexMismatchInPolygons::Tolerable_error)
41514 double rev_error = 0.0;
41515 for(
unsigned i=0;i<2;i++)
41517 const double dist =
41518 initial_vertex_of_previous_segment[i] -
41519 (*--vector_vertex_node.end())[i];
41520 rev_error += dist*dist;
41522 rev_error = sqrt(rev_error);
41526 ToleranceForVertexMismatchInPolygons::Tolerable_error)
41528 std::ostringstream error_stream;
41530 <<
"The distance between the first node of the current\n"
41531 <<
"line segment (boundary " << bound <<
") and either end of "
41532 <<
"the previous line segment\n"
41533 <<
"(boundary " << prev_seg_boundary_id <<
") is bigger than "
41534 <<
"the desired tolerance " <<
41535 ToleranceForVertexMismatchInPolygons::Tolerable_error <<
".\n"
41536 <<
"This suggests that the polylines defining the polygonal\n"
41537 <<
"representation are not properly ordered.\n"
41538 <<
"Fail on last vertex of polyline: ("
41539 << prev_seg_boundary_id<<
") and\nfirst vertex of polyline ("
41540 << bound <<
").\nThis should have failed when first trying to"
41541 <<
" construct the\npolygon.\n";
41542 throw OomphLibError(error_stream.str(),
41543 "RefineableTriangleMesh::update_polygon_after_restart()",
41544 OOMPH_EXCEPTION_LOCATION);
41550 std::reverse(vector_vertex_node.begin(),
41551 vector_vertex_node.end());
41552 polygon_pt->polyline_pt(p-1)->reverse();
41558 polygon_pt->polyline_pt(p-1)->reverse();
41564 std::ostringstream error_stream;
41566 <<
"The distance between the first node of the current\n"
41567 <<
"line segment (boundary " << bound <<
") and either end of "
41568 <<
"the previous line segment\n"
41569 <<
"(boundary " << prev_seg_boundary_id <<
") is bigger than the "
41570 <<
"desired tolerance " <<
41571 ToleranceForVertexMismatchInPolygons::Tolerable_error <<
".\n"
41572 <<
"This suggests that the polylines defining the polygonal\n"
41573 <<
"representation are not properly ordered.\n"
41574 <<
"Fail on last vertex of polyline: (" << prev_seg_boundary_id
41575 <<
") and\nfirst vertex of polyline (" << bound <<
").\n"
41576 <<
"This should have failed when first trying to construct the\n"
41578 throw OomphLibError(
41579 error_stream.str(),
41580 "RefineableTriangleMesh::update_polygon_after_restart()",
41581 OOMPH_EXCEPTION_LOCATION);
41587 std::reverse(vector_vertex_node.begin(),vector_vertex_node.end());
41602 n_vertex = vector_vertex_node.size();
41606 TriangleMeshPolyLine *tmp_polyline_pt =
41607 new TriangleMeshPolyLine(vector_vertex_node,bound);
41618 TriangleMeshCurveSection *tmp_curve_section_pt = tmp_polyline_pt;
41622 double unrefinement_tolerance=
41623 polygon_pt->polyline_pt(p)->unrefinement_tolerance();
41626 double refinement_tolerance=
41627 polygon_pt->polyline_pt(p)->refinement_tolerance();
41630 tmp_polyline_pt->set_unrefinement_tolerance(
41631 unrefinement_tolerance);
41632 tmp_polyline_pt->set_refinement_tolerance(
41633 refinement_tolerance);
41636 double maximum_length = polygon_pt->polyline_pt(p)->maximum_length();
41637 tmp_polyline_pt->set_maximum_length(maximum_length);
41643 this->copy_connection_information(polygon_pt->polyline_pt(p),
41644 tmp_curve_section_pt);
41650 bool delete_it_on_destructor =
false;
41652 std::set<TriangleMeshCurveSection*>::iterator it =
41653 this->Free_curve_section_pt.find(polygon_pt->curve_section_pt(p));
41655 if (it!=this->Free_curve_section_pt.end())
41657 this->Free_curve_section_pt.erase(it);
41658 delete polygon_pt->curve_section_pt(p);
41659 delete_it_on_destructor =
true;
41664 polygon_pt->curve_section_pt(p) = tmp_polyline_pt;
41667 this->Boundary_curve_section_pt[bound] = polygon_pt->curve_section_pt(p);
41669 if (delete_it_on_destructor)
41671 this->Free_curve_section_pt.insert(polygon_pt->curve_section_pt(p));
41674 #ifdef OOMPH_HAS_MPI
41677 if (this->is_mesh_distributed() && nsub_boundaries > 1)
41682 this->Boundary_subpolylines[bound].clear();
41684 this->Boundary_subpolylines[bound].resize(nsub_boundaries);
41685 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
41689 TriangleMeshPolyLine *sub_tmp_polyline_pt =
41690 new TriangleMeshPolyLine(sub_vector_vertex_node[isub], bound, isub);
41694 this->Boundary_subpolylines[bound][isub] = sub_tmp_polyline_pt;
41706 #endif // OOMPH_HAS_MPI
41712 delete mesh_geom_obj_pt;
41717 for(
unsigned p=0;p<n_polyline;p++)
41719 face_mesh_pt[p]->flush_node_storage();
41720 delete face_mesh_pt[p];
41729 template <
class ELEMENT>
41739 Vector<Mesh*> face_mesh_pt;
41740 get_face_mesh_representation(open_curve_pt,face_mesh_pt);
41744 Vector<double> vertex_coord(3);
41745 Vector<double> bound_left(1);
41746 Vector<double> bound_right(1);
41748 const unsigned ncurve_section = open_curve_pt->ncurve_section();
41750 for(
unsigned cs = 0; cs < ncurve_section; cs++)
41758 MeshAsGeomObject* mesh_geom_obj_pt=
new MeshAsGeomObject(face_mesh_pt[cs]);
41761 const unsigned bound = open_curve_pt->curve_section_pt(cs)->boundary_id();
41770 const unsigned nface_element = face_mesh_pt[cs]->nelement();
41774 Vector<FiniteElement*> non_halo_doubled_face_element_pt;
41777 std::map<FiniteElement*,unsigned> face_element_index_on_boundary;
41780 std::map<FiniteElement*,bool> face_element_done;
41782 for(
unsigned ef = 0; ef < nface_element; ++ef)
41784 FiniteElement* ele_face_pt = face_mesh_pt[cs]->finite_element_pt(ef);
41789 #ifdef OOMPH_HAS_MPI
41790 if (this->is_mesh_distributed())
41793 if (ele_face_pt->is_halo()) {
continue;}
41798 if (!face_element_done[ele_face_pt])
41803 non_halo_doubled_face_element_pt.push_back(ele_face_pt);
41805 face_element_index_on_boundary[ele_face_pt] = ef;
41807 face_element_done[ele_face_pt] =
true;
41809 const unsigned nnodes = ele_face_pt->nnode();
41812 Node* left_node_pt = ele_face_pt->node_pt(0);
41813 Node* right_node_pt = ele_face_pt->node_pt(nnodes-1);
41818 bool found_other_side_face_ele =
false;
41820 for (
unsigned iface = 0; iface < nface_element; iface++)
41823 FiniteElement *cele_face_pt =
41824 face_mesh_pt[cs]->finite_element_pt(iface);
41826 if (!face_element_done[cele_face_pt])
41828 Node* cleft_node_pt = cele_face_pt->node_pt(0);
41829 Node* cright_node_pt = cele_face_pt->node_pt(nnodes-1);
41832 if ((left_node_pt == cleft_node_pt &&
41833 right_node_pt == cright_node_pt) ||
41834 (left_node_pt == cright_node_pt &&
41835 right_node_pt == cleft_node_pt))
41838 non_halo_doubled_face_element_pt.push_back(cele_face_pt);
41840 face_element_done[cele_face_pt] =
true;
41842 face_element_index_on_boundary[cele_face_pt] = iface;
41845 found_other_side_face_ele =
true;
41853 if (!found_other_side_face_ele)
41855 std::ostringstream error_message;
41857 <<
"The face element at the other side of the boundary ("
41858 << bound <<
") was not found!!\n"
41859 <<
"These are the nodes of the face element:\n"
41860 <<
"("<<left_node_pt->x(0)<<
", "<<left_node_pt->x(1)<<
") "
41861 <<
"and ("<<right_node_pt->x(0)<<
","<<right_node_pt->x(1)<<
")\n\n";
41862 throw OomphLibError(error_message.str(),
41863 "RefineableTriangleMesh::update_open_curve_after_restart()",
41864 OOMPH_EXCEPTION_LOCATION);
41873 face_element_done.clear();
41878 std::set<Vector<double> > vertex_nodes;
41882 Vector<Vector<double> > tmp_vector_vertex_node;
41887 Vector<Vector<double> > vector_vertex_node;
41889 #ifdef OOMPH_HAS_MPI
41894 std::vector<bool> internal_to_shared_boundary;
41901 Vector<std::set<Vector<double> > > sub_vertex_nodes;
41905 Vector<Vector<Vector<double> > > sub_tmp_vector_vertex_node;
41910 Vector<Vector<Vector<double> > > sub_vector_vertex_node;
41919 unsigned nsorted_face_elements = 0;
41921 #ifdef OOMPH_HAS_MPI
41923 unsigned nsub_boundaries = 0;
41924 #endif // #ifdef OOMPH_HAS_MPI
41927 const unsigned nnon_halo_doubled_face_ele =
41928 non_halo_doubled_face_element_pt.size();
41932 while(nsorted_face_elements < nnon_halo_doubled_face_ele)
41935 FiniteElement* ele_face_pt = 0;
41936 FiniteElement* repeated_ele_face_pt = 0;
41938 bool found_initial_face_element =
false;
41944 bool both_root_face_elements_are_nonhalo =
false;
41946 unsigned iface = 0;
41947 for (iface = 0; iface < nnon_halo_doubled_face_ele; iface+=2)
41949 ele_face_pt = non_halo_doubled_face_element_pt[iface];
41951 if (!face_element_done[ele_face_pt])
41954 face_element_done[ele_face_pt] =
true;
41956 repeated_ele_face_pt = non_halo_doubled_face_element_pt[iface+1];
41958 face_element_done[repeated_ele_face_pt] =
true;
41960 #ifdef OOMPH_HAS_MPI
41961 if (!repeated_ele_face_pt->is_halo())
41962 {both_root_face_elements_are_nonhalo =
true;}
41963 #endif // #ifdef OOMPH_HAS_MPI
41967 nsorted_face_elements+=2;
41971 found_initial_face_element =
true;
41978 if (!found_initial_face_element)
41980 std::ostringstream error_message;
41982 <<
"Could not find an initial face element for the current segment\n";
41984 throw OomphLibError(error_message.str(),
41985 OOMPH_CURRENT_FUNCTION,
41986 OOMPH_EXCEPTION_LOCATION);
41993 std::set<Vector<double> > local_vertex_nodes;
41997 Vector<Vector<double> > local_tmp_vector_vertex_node;
42005 const unsigned nnode = ele_face_pt->nnode();
42008 ele_face_pt->node_pt(0)->get_coordinates_on_boundary(bound,bound_left);
42009 vertex_coord[0] = bound_left[0];
42012 for(
unsigned i=0;i<2;i++)
42014 vertex_coord[i+1] = ele_face_pt->node_pt(0)->x(i);
42016 local_vertex_nodes.insert(vertex_coord);
42020 ele_face_pt->node_pt(nnode-1)->get_coordinates_on_boundary(bound,
42022 vertex_coord[0] = bound_right[0];
42025 for(
unsigned i=0;i<2;i++)
42027 vertex_coord[i+1] = ele_face_pt->node_pt(nnode-1)->x(i);
42029 local_vertex_nodes.insert(vertex_coord);
42032 Node *first_node_pt = ele_face_pt->node_pt(0);
42033 Node *last_node_pt = ele_face_pt->node_pt(nnode-1);
42037 bool face_element_added =
false;
42047 for (
unsigned iiface=iface;
42048 iiface<nnon_halo_doubled_face_ele;iiface+=2)
42050 face_element_added =
false;
42051 ele_face_pt = non_halo_doubled_face_element_pt[iiface];
42058 repeated_ele_face_pt = non_halo_doubled_face_element_pt[iiface+1];
42059 bool both_face_elements_are_nonhalo =
false;
42061 #ifdef OOMPH_HAS_MPI
42062 if (!repeated_ele_face_pt->is_halo())
42063 {both_face_elements_are_nonhalo =
true;}
42064 #endif // #ifdef OOMPH_HAS_MPI
42066 if (!face_element_done[ele_face_pt] &&
42067 (both_face_elements_are_nonhalo ==
42068 both_root_face_elements_are_nonhalo))
42071 const unsigned nlnode = ele_face_pt->nnode();
42072 Node* left_node_pt = ele_face_pt->node_pt(0);
42073 Node* right_node_pt = ele_face_pt->node_pt(nlnode-1);
42075 if (left_node_pt == first_node_pt)
42077 first_node_pt = right_node_pt;
42078 face_element_added =
true;
42080 else if (left_node_pt == last_node_pt)
42082 last_node_pt = right_node_pt;
42083 face_element_added =
true;
42085 else if (right_node_pt == first_node_pt)
42087 first_node_pt = left_node_pt;
42088 face_element_added =
true;
42090 else if (right_node_pt == last_node_pt)
42092 last_node_pt = left_node_pt;
42093 face_element_added =
true;
42096 if (face_element_added)
42100 left_node_pt->get_coordinates_on_boundary(bound,bound_left);
42101 vertex_coord[0] = bound_left[0];
42104 for(
unsigned i=0;i<2;i++)
42106 vertex_coord[i+1] = left_node_pt->x(i);
42108 local_vertex_nodes.insert(vertex_coord);
42112 right_node_pt->get_coordinates_on_boundary(bound,bound_right);
42113 vertex_coord[0] = bound_right[0];
42116 for(
unsigned i=0;i<2;i++)
42118 vertex_coord[i+1] = right_node_pt->x(i);
42120 local_vertex_nodes.insert(vertex_coord);
42124 face_element_done[ele_face_pt] =
true;
42127 repeated_ele_face_pt = non_halo_doubled_face_element_pt[iiface+1];
42128 face_element_done[repeated_ele_face_pt] =
true;
42130 nsorted_face_elements+=2;
42137 }
while(face_element_added &&
42138 (nsorted_face_elements < nnon_halo_doubled_face_ele));
42146 const unsigned nlocal_nodes = local_vertex_nodes.size();
42148 local_tmp_vector_vertex_node.resize(nlocal_nodes);
42151 unsigned counter = 0;
42152 std::set<Vector<double> >::iterator it_vertex;
42153 for (it_vertex = local_vertex_nodes.begin();
42154 it_vertex != local_vertex_nodes.end();
42157 local_tmp_vector_vertex_node[counter].resize(3);
42158 local_tmp_vector_vertex_node[counter][0] = (*it_vertex)[0];
42159 local_tmp_vector_vertex_node[counter][1] = (*it_vertex)[1];
42160 local_tmp_vector_vertex_node[counter][2] = (*it_vertex)[2];
42167 if (local_tmp_vector_vertex_node[nlocal_nodes-1][2] <
42168 local_tmp_vector_vertex_node[0][2])
42170 std::reverse(local_tmp_vector_vertex_node.begin(),
42171 local_tmp_vector_vertex_node.end());
42173 else if (local_tmp_vector_vertex_node[nlocal_nodes-1][2] ==
42174 local_tmp_vector_vertex_node[0][2])
42176 if (local_tmp_vector_vertex_node[nlocal_nodes-1][1] <
42177 local_tmp_vector_vertex_node[0][1])
42179 std::reverse(local_tmp_vector_vertex_node.begin(),
42180 local_tmp_vector_vertex_node.end());
42191 local_vertex_nodes.clear();
42196 const unsigned nnew_nodes = local_tmp_vector_vertex_node.size();
42197 for (
unsigned i = 0; i < nnew_nodes; i++)
42199 vertex_coord[0] = local_tmp_vector_vertex_node[i][0];
42200 vertex_coord[1] = local_tmp_vector_vertex_node[i][1];
42201 vertex_coord[2] = local_tmp_vector_vertex_node[i][2];
42202 vertex_nodes.insert(vertex_coord);
42203 local_vertex_nodes.insert(vertex_coord);
42206 #ifdef OOMPH_HAS_MPI
42207 if (this->is_mesh_distributed())
42212 sub_vertex_nodes.push_back(local_vertex_nodes);
42218 if (both_root_face_elements_are_nonhalo)
42219 {internal_to_shared_boundary.push_back(
false);}
42221 {internal_to_shared_boundary.push_back(
true);}
42231 const unsigned npoly_vertex = vertex_nodes.size();
42232 tmp_vector_vertex_node.resize(npoly_vertex);
42233 unsigned count = 0;
42234 std::set<Vector<double> >::iterator it;
42235 for (it = vertex_nodes.begin(); it!=vertex_nodes.end(); ++it)
42237 tmp_vector_vertex_node[count].resize(3);
42238 tmp_vector_vertex_node[count][0] = (*it)[0];
42239 tmp_vector_vertex_node[count][1] = (*it)[1];
42240 tmp_vector_vertex_node[count][2] = (*it)[2];
42244 #ifdef OOMPH_HAS_MPI
42249 const unsigned nsub_boundaries_set = sub_vertex_nodes.size();
42250 const unsigned ninternal_to_shared_boundaries =
42251 internal_to_shared_boundary.size();
42252 if (nsub_boundaries_set != ninternal_to_shared_boundaries)
42254 std::ostringstream error_message;
42256 <<
"The number of found sub-boundaries and the number of marked "
42257 <<
"internal\nboundaries are different\n"
42258 <<
"Number of found sub-boundaries: ("<<nsub_boundaries_set<<
")\n"
42259 <<
"Number of marked internal boundaries: ("
42260 << ninternal_to_shared_boundaries <<
")\n\n";
42261 throw OomphLibError(error_message.str(),
42262 "RefineableTriangleMesh::update_open_curve_after_restart()",
42263 OOMPH_EXCEPTION_LOCATION);
42269 if (nsub_boundaries_set != nsub_boundaries)
42271 std::ostringstream error_message;
42273 <<
"The number of found sub-boundaries and the number of counted\n"
42274 <<
"sub-boundaries are different:\n"
42275 <<
"Number of found sub-boundaries: ("<<nsub_boundaries_set<<
")\n"
42276 <<
"Number of counted sub-boundaries: ("<<nsub_boundaries<<
")\n\n";
42277 throw OomphLibError(error_message.str(),
42278 "RefineableTriangleMesh::update_open_curve_after_restart()",
42279 OOMPH_EXCEPTION_LOCATION);
42284 if (this->is_mesh_distributed() && nsub_boundaries > 1)
42287 this->Boundary_was_splitted[bound] =
true;
42289 sub_tmp_vector_vertex_node.resize(nsub_boundaries);
42290 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
42293 const unsigned nsubpoly_vertex = sub_vertex_nodes[isub].size();
42294 sub_tmp_vector_vertex_node[isub].resize(nsubpoly_vertex);
42295 unsigned subcount = 0;
42296 std::set<Vector<double> >::iterator subit;
42297 for(subit = sub_vertex_nodes[isub].begin();
42298 subit != sub_vertex_nodes[isub].end(); ++subit)
42300 sub_tmp_vector_vertex_node[isub][subcount].resize(3);
42301 sub_tmp_vector_vertex_node[isub][subcount][0] = (*subit)[0];
42302 sub_tmp_vector_vertex_node[isub][subcount][1] = (*subit)[1];
42303 sub_tmp_vector_vertex_node[isub][subcount][2] = (*subit)[2];
42309 #endif // OOMPH_HAS_MPI
42313 unsigned n_vertex=tmp_vector_vertex_node.size();
42316 vector_vertex_node.resize(n_vertex);
42317 for(
unsigned i=0;i<n_vertex;i++)
42319 vector_vertex_node[i].resize(2);
42320 vector_vertex_node[i][0]=tmp_vector_vertex_node[i][1];
42321 vector_vertex_node[i][1]=tmp_vector_vertex_node[i][2];
42324 #ifdef OOMPH_HAS_MPI
42327 if (this->is_mesh_distributed() && nsub_boundaries > 1)
42332 sub_vector_vertex_node.resize(nsub_boundaries);
42333 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
42335 const unsigned subn_vertex =
42336 sub_tmp_vector_vertex_node[isub].size();
42338 sub_vector_vertex_node[isub].resize(subn_vertex);
42339 for(
unsigned i=0;i<subn_vertex;i++)
42341 sub_vector_vertex_node[isub][i].resize(2);
42342 sub_vector_vertex_node[isub][i][0]=
42343 sub_tmp_vector_vertex_node[isub][i][1];
42344 sub_vector_vertex_node[isub][i][1]=
42345 sub_tmp_vector_vertex_node[isub][i][2];
42355 #endif // OOMPH_HAS_MPI
42360 #ifdef OOMPH_HAS_MPI
42364 if (!this->is_mesh_distributed())
42370 Vector<double> final_vertex_of_previous_segment;
42371 unsigned n_prev_vertex =
42372 open_curve_pt->curve_section_pt(cs-1)->nvertex();
42373 final_vertex_of_previous_segment =
42374 open_curve_pt->polyline_pt(cs-1)->
42375 vertex_coordinate(n_prev_vertex-1);
42377 unsigned prev_seg_boundary_id =
42378 open_curve_pt->curve_section_pt(cs-1)->boundary_id();
42382 double error = 0.0;
42383 for(
unsigned i=0;i<2;i++)
42385 const double dist =
42386 final_vertex_of_previous_segment[i] -
42387 (*vector_vertex_node.begin())[i];
42388 error += dist*dist;
42390 error = sqrt(error);
42394 if(error > ToleranceForVertexMismatchInPolygons::Tolerable_error)
42398 double rev_error = 0.0;
42399 for(
unsigned i=0;i<2;i++)
42401 const double dist =
42402 final_vertex_of_previous_segment[i] -
42403 (*--vector_vertex_node.end())[i];
42404 rev_error += dist*dist;
42406 rev_error = sqrt(rev_error);
42409 ToleranceForVertexMismatchInPolygons::Tolerable_error)
42418 Vector<double> initial_vertex_of_previous_segment;
42420 initial_vertex_of_previous_segment =
42421 open_curve_pt->polyline_pt(cs-1)->vertex_coordinate(0);
42423 unsigned prev_seg_boundary_id =
42424 open_curve_pt->curve_section_pt(cs-1)->boundary_id();
42428 double error = 0.0;
42429 for(
unsigned i=0;i<2;i++)
42431 const double dist =
42432 initial_vertex_of_previous_segment[i] -
42433 (*vector_vertex_node.begin())[i];
42434 error += dist*dist;
42436 error = sqrt(error);
42440 if(error > ToleranceForVertexMismatchInPolygons::Tolerable_error)
42444 double rev_error = 0.0;
42445 for(
unsigned i=0;i<2;i++)
42447 const double dist =
42448 initial_vertex_of_previous_segment[i] -
42449 (*--vector_vertex_node.end())[i];
42450 rev_error += dist*dist;
42452 rev_error = sqrt(rev_error);
42456 ToleranceForVertexMismatchInPolygons::Tolerable_error)
42458 std::ostringstream error_stream;
42460 <<
"The distance between the first node of the current\n"
42461 <<
"line segment (boundary "<<bound<<
") and either end of "
42462 <<
"the previous line segment\n"
42463 <<
"(boundary "<<prev_seg_boundary_id<<
") is bigger than"
42464 <<
" the desired tolerance " <<
42465 ToleranceForVertexMismatchInPolygons::Tolerable_error<<
".\n"
42466 <<
"This suggests that the polylines defining the polygonal\n"
42467 <<
"representation are not properly ordered.\n"
42468 <<
"Fail on last vertex of polyline: ("
42469 <<prev_seg_boundary_id<<
") and\nfirst vertex of polyline ("
42470 <<bound<<
").\nThis should have failed when first trying to "
42471 <<
"construct the\npolygon.\n";
42472 throw OomphLibError(error_stream.str(),
42473 "RefineableTriangleMesh::update_open_curve_after_restart()",
42474 OOMPH_EXCEPTION_LOCATION);
42480 std::reverse(vector_vertex_node.begin(),
42481 vector_vertex_node.end());
42482 open_curve_pt->polyline_pt(cs-1)->reverse();
42488 open_curve_pt->polyline_pt(cs-1)->reverse();
42494 std::ostringstream error_stream;
42496 <<
"The distance between the first node of the current\n"
42497 <<
"line segment (boundary " << bound <<
") and either end of "
42498 <<
"the previous line segment\n"
42499 <<
"(boundary " << prev_seg_boundary_id <<
") is bigger than the "
42500 <<
"desired tolerance " <<
42501 ToleranceForVertexMismatchInPolygons::Tolerable_error <<
".\n"
42502 <<
"This suggests that the polylines defining the polygonal\n"
42503 <<
"representation are not properly ordered.\n"
42504 <<
"Fail on last vertex of polyline: (" << prev_seg_boundary_id
42505 <<
") and\nfirst vertex of polyline (" << bound <<
").\n"
42506 <<
"This should have failed when first trying to construct the\n"
42508 throw OomphLibError(
42509 error_stream.str(),
42510 "RefineableTriangleMesh::update_open_curve_after_restart()",
42511 OOMPH_EXCEPTION_LOCATION);
42517 std::reverse(vector_vertex_node.begin(),vector_vertex_node.end());
42535 n_vertex = vector_vertex_node.size();
42539 TriangleMeshPolyLine *tmp_polyline_pt =
42540 new TriangleMeshPolyLine(vector_vertex_node,bound);
42544 TriangleMeshCurveSection *tmp_curve_section_pt = tmp_polyline_pt;
42548 double unrefinement_tolerance=
42549 open_curve_pt->polyline_pt(cs)->unrefinement_tolerance();
42552 double refinement_tolerance=
42553 open_curve_pt->polyline_pt(cs)->refinement_tolerance();
42556 tmp_polyline_pt->set_unrefinement_tolerance(unrefinement_tolerance);
42557 tmp_polyline_pt->set_refinement_tolerance(refinement_tolerance);
42560 double maximum_length = open_curve_pt->polyline_pt(cs)->maximum_length();
42561 tmp_polyline_pt->set_maximum_length(maximum_length);
42567 this->copy_connection_information(open_curve_pt->polyline_pt(cs),
42568 tmp_curve_section_pt);
42574 bool delete_it_on_destructor =
false;
42576 std::set<TriangleMeshCurveSection*>::iterator it =
42577 this->Free_curve_section_pt.find(open_curve_pt->curve_section_pt(cs));
42579 if (it!=this->Free_curve_section_pt.end())
42581 this->Free_curve_section_pt.erase(it);
42582 delete open_curve_pt->curve_section_pt(cs);
42583 delete_it_on_destructor =
true;
42588 open_curve_pt->curve_section_pt(cs) = tmp_polyline_pt;
42591 this->Boundary_curve_section_pt[bound]=open_curve_pt->curve_section_pt(cs);
42593 if (delete_it_on_destructor)
42595 this->Free_curve_section_pt.insert(open_curve_pt->curve_section_pt(cs));
42598 #ifdef OOMPH_HAS_MPI
42602 if (this->is_mesh_distributed() && nsub_boundaries == 1)
42605 this->Boundary_marked_as_shared_boundary[bound].clear();
42608 this->Boundary_marked_as_shared_boundary[bound].push_back(
42609 internal_to_shared_boundary[0]);
42613 else if (this->is_mesh_distributed() && nsub_boundaries > 1)
42618 this->Boundary_subpolylines[bound].clear();
42620 this->Boundary_subpolylines[bound].resize(nsub_boundaries);
42623 this->Boundary_marked_as_shared_boundary[bound].clear();
42626 this->Boundary_marked_as_shared_boundary[bound].resize(nsub_boundaries);
42627 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
42631 TriangleMeshPolyLine *sub_tmp_polyline_pt =
42632 new TriangleMeshPolyLine(sub_vector_vertex_node[isub], bound, isub);
42636 this->Boundary_subpolylines[bound][isub] = sub_tmp_polyline_pt;
42640 this->Boundary_marked_as_shared_boundary[bound][isub] =
42641 internal_to_shared_boundary[isub];
42651 #endif // OOMPH_HAS_MPI
42657 delete mesh_geom_obj_pt;
42662 for(
unsigned p = 0; p < ncurve_section; p++)
42664 face_mesh_pt[p]->flush_node_storage();
42665 delete face_mesh_pt[p];
42670 #ifdef OOMPH_HAS_MPI
42674 template <
class ELEMENT>
42677 &vector_polyline_pt)
42680 const unsigned npolylines = vector_polyline_pt.size();
42681 for (
unsigned pp = 0; pp < npolylines; pp++)
42684 const unsigned b = vector_polyline_pt[pp]->boundary_id();
42689 std::map<std::pair<Node*, Node*>, FiniteElement*> halo_edge_element_pt;
42690 std::map<std::pair<Node*, Node*>, FiniteElement*> nonhalo_edge_element_pt;
42693 Vector<Node*> halo_edge_nodes_pt;
42694 Vector<Node*> nonhalo_edge_nodes_pt;
42697 const unsigned nshared_bound_ele = this->nshared_boundary_element(b);
42698 for (
unsigned e = 0; e < nshared_bound_ele; e++)
42701 FiniteElement* current_ele_pt = this->shared_boundary_element_pt(b, e);
42704 Node *first_node_pt = current_ele_pt->node_pt(0);
42705 Node *second_node_pt = current_ele_pt->node_pt(1);
42706 Node *third_node_pt = current_ele_pt->node_pt(2);
42709 if (!current_ele_pt->is_halo())
42712 nonhalo_edge_nodes_pt.push_back(first_node_pt);
42713 nonhalo_edge_nodes_pt.push_back(second_node_pt);
42715 nonhalo_edge_nodes_pt.push_back(second_node_pt);
42716 nonhalo_edge_nodes_pt.push_back(third_node_pt);
42718 nonhalo_edge_nodes_pt.push_back(third_node_pt);
42719 nonhalo_edge_nodes_pt.push_back(first_node_pt);
42722 std::pair<Node*, Node*> edge1 = std::make_pair(first_node_pt,
42724 nonhalo_edge_element_pt[edge1] = current_ele_pt;
42726 std::pair<Node*, Node*> edge2 = std::make_pair(second_node_pt,
42728 nonhalo_edge_element_pt[edge2] = current_ele_pt;
42730 std::pair<Node*, Node*> edge3 = std::make_pair(third_node_pt,
42732 nonhalo_edge_element_pt[edge3] = current_ele_pt;
42737 halo_edge_nodes_pt.push_back(first_node_pt);
42738 halo_edge_nodes_pt.push_back(second_node_pt);
42740 halo_edge_nodes_pt.push_back(second_node_pt);
42741 halo_edge_nodes_pt.push_back(third_node_pt);
42743 halo_edge_nodes_pt.push_back(third_node_pt);
42744 halo_edge_nodes_pt.push_back(first_node_pt);
42747 std::pair<Node*, Node*> edge1 = std::make_pair(first_node_pt,
42749 halo_edge_element_pt[edge1] = current_ele_pt;
42751 std::pair<Node*, Node*> edge2 = std::make_pair(second_node_pt,
42753 halo_edge_element_pt[edge2] = current_ele_pt;
42755 std::pair<Node*, Node*> edge3 = std::make_pair(third_node_pt,
42757 halo_edge_element_pt[edge3] = current_ele_pt;
42765 std::map<std::pair<Node*,Node*>,
bool> edge_done;
42768 Vector<std::pair<Node*, Node*> > unsorted_edges;
42772 Vector<Vector<FiniteElement*> > unsorted_edges_elements_pt;
42774 const unsigned nnonhalo_edge_nodes = nonhalo_edge_nodes_pt.size();
42775 for (
unsigned i = 0; i < nnonhalo_edge_nodes; i+=2)
42777 Vector<Node*> currenti_edge(2);
42778 currenti_edge[0] = nonhalo_edge_nodes_pt[i];
42779 currenti_edge[1] = nonhalo_edge_nodes_pt[i+1];
42782 std::pair<Node*, Node*> new_edge =
42783 std::make_pair(currenti_edge[0], currenti_edge[1]);
42785 if (!edge_done[new_edge])
42787 const unsigned nhalo_edge_nodes = halo_edge_nodes_pt.size();
42788 for (
unsigned j = 0; j < nhalo_edge_nodes; j+=2)
42790 Vector<Node*> currentj_edge(2);
42791 currentj_edge[0] = halo_edge_nodes_pt[j];
42792 currentj_edge[1] = halo_edge_nodes_pt[j+1];
42795 if (currenti_edge[0] == currentj_edge[0] &&
42796 currenti_edge[1] == currentj_edge[1])
42799 unsorted_edges.push_back(new_edge);
42802 Vector<FiniteElement*> tmp_edge_element_pt;
42804 FiniteElement* nonhalo_ele_pt = nonhalo_edge_element_pt[new_edge];
42805 FiniteElement* halo_ele_pt = halo_edge_element_pt[new_edge];
42807 tmp_edge_element_pt.push_back(nonhalo_ele_pt);
42808 tmp_edge_element_pt.push_back(halo_ele_pt);
42811 unsorted_edges_elements_pt.push_back(tmp_edge_element_pt);
42814 edge_done[new_edge] =
true;
42822 else if (currenti_edge[0] == currentj_edge[1] &&
42823 currenti_edge[1] == currentj_edge[0])
42826 std::pair<Node*, Node*> new_edge =
42827 std::make_pair(currenti_edge[0], currenti_edge[1]);
42830 unsorted_edges.push_back(new_edge);
42833 std::pair<Node*, Node*> rev_new_edge =
42834 std::make_pair(currentj_edge[0], currentj_edge[1]);
42837 Vector<FiniteElement*> tmp_edge_element_pt;
42839 FiniteElement* nonhalo_ele_pt = nonhalo_edge_element_pt[new_edge];
42840 FiniteElement* halo_ele_pt = halo_edge_element_pt[rev_new_edge];
42842 tmp_edge_element_pt.push_back(nonhalo_ele_pt);
42843 tmp_edge_element_pt.push_back(halo_ele_pt);
42846 unsorted_edges_elements_pt.push_back(tmp_edge_element_pt);
42849 edge_done[new_edge] =
true;
42867 std::map<std::pair<Node*,Node*>,
bool> edge_sorted;
42869 const unsigned nunsorted_edges = unsorted_edges.size();
42874 if (nshared_bound_ele / 2 != nunsorted_edges)
42876 std::ostringstream error_message;
42878 <<
"The number of shared boundary elements (" << nshared_bound_ele
42879 <<
") is not the double\nof the number of unsorted edges ("
42880 << nunsorted_edges <<
") for the current boundary ("<< b <<
")\n\n";
42881 throw OomphLibError(error_message.str(),
42882 "RefineableTriangleMesh::update_shared_curve_after_restart()",
42883 OOMPH_EXCEPTION_LOCATION);
42887 unsigned nsorted_edges = 0;
42891 std::list<Node*> sorted_nodes;
42894 std::list<FiniteElement*> sorted_edges_elements_pt;
42897 std::pair<Node*,Node*> edge = unsorted_edges[0];
42901 edge_sorted[edge] =
true;
42904 Node *first_node_pt = edge.first;
42905 Node *last_node_pt = edge.second;
42908 sorted_nodes.push_back(first_node_pt);
42909 sorted_nodes.push_back(last_node_pt);
42912 sorted_edges_elements_pt.push_back(unsorted_edges_elements_pt[0][0]);
42913 sorted_edges_elements_pt.push_back(unsorted_edges_elements_pt[0][1]);
42917 while (nsorted_edges < nunsorted_edges)
42920 bool node_added =
false;
42924 for (
unsigned iedge = 1; iedge < nunsorted_edges; iedge++)
42926 edge = unsorted_edges[iedge];
42929 if (!edge_sorted[edge])
42932 Node* left_node_pt = edge.first;
42933 Node* right_node_pt = edge.second;
42935 if (left_node_pt == first_node_pt)
42938 sorted_nodes.push_front(right_node_pt);
42939 first_node_pt = right_node_pt;
42943 sorted_edges_elements_pt.push_front(
42944 unsorted_edges_elements_pt[iedge][1]);
42945 sorted_edges_elements_pt.push_front(
42946 unsorted_edges_elements_pt[iedge][0]);
42948 else if (left_node_pt == last_node_pt)
42951 sorted_nodes.push_back(right_node_pt);
42952 last_node_pt = right_node_pt;
42956 sorted_edges_elements_pt.push_back(
42957 unsorted_edges_elements_pt[iedge][0]);
42958 sorted_edges_elements_pt.push_back(
42959 unsorted_edges_elements_pt[iedge][1]);
42961 else if (right_node_pt == first_node_pt)
42964 sorted_nodes.push_front(left_node_pt);
42965 first_node_pt = left_node_pt;
42969 sorted_edges_elements_pt.push_front(
42970 unsorted_edges_elements_pt[iedge][1]);
42971 sorted_edges_elements_pt.push_front(
42972 unsorted_edges_elements_pt[iedge][0]);
42974 else if (right_node_pt == last_node_pt)
42977 sorted_nodes.push_back(left_node_pt);
42978 last_node_pt = left_node_pt;
42982 sorted_edges_elements_pt.push_back(
42983 unsorted_edges_elements_pt[iedge][0]);
42984 sorted_edges_elements_pt.push_back(
42985 unsorted_edges_elements_pt[iedge][1]);
42992 edge_sorted[edge] =
true;
43007 unsigned nvertex = sorted_nodes.size();
43009 Vector<Vector<double> > polyline_vertices(nvertex);
43012 unsigned counter = 0;
43013 for (std::list<Node*>::iterator it_nodes = sorted_nodes.begin();
43014 it_nodes != sorted_nodes.end();
43017 polyline_vertices[counter].resize(2);
43018 polyline_vertices[counter][0] = (*it_nodes)->x(0);
43019 polyline_vertices[counter][1] = (*it_nodes)->x(1);
43026 if (polyline_vertices[nvertex-1][1] < polyline_vertices[0][1])
43028 std::reverse(polyline_vertices.begin(), polyline_vertices.end());
43030 else if (polyline_vertices[nvertex-1][1] == polyline_vertices[0][1])
43032 if (polyline_vertices[nvertex-1][0] < polyline_vertices[0][0])
43034 std::reverse(polyline_vertices.begin(), polyline_vertices.end());
43039 TriangleMeshPolyLine *new_polyline_pt =
43040 new TriangleMeshPolyLine(polyline_vertices, b);
43043 TriangleMeshCurveSection *curve_section_pt = vector_polyline_pt[pp];
43047 this->copy_connection_information(curve_section_pt, new_polyline_pt);
43052 bool delete_it_on_destructor =
false;
43056 std::set<TriangleMeshCurveSection*>::iterator it =
43057 this->Free_curve_section_pt.find(curve_section_pt);
43059 if (it!=this->Free_curve_section_pt.end())
43061 this->Free_curve_section_pt.erase(it);
43062 delete curve_section_pt;
43063 delete_it_on_destructor =
true;
43067 vector_polyline_pt[pp] = new_polyline_pt;
43070 TriangleMeshCurveSection *new_curve_section_pt = vector_polyline_pt[pp];
43073 this->Boundary_curve_section_pt[b] = new_curve_section_pt;
43075 if (delete_it_on_destructor)
43077 this->Free_curve_section_pt.insert(new_curve_section_pt);
43090 template <
class ELEMENT>
43095 std::ofstream some_file;
43096 fill_boundary_elements_and_nodes_for_internal_boundaries(some_file);
43103 template <
class ELEMENT>
43106 std::ofstream& outfile)
43109 const unsigned nproc = this->communicator_pt()->nproc();
43111 unsigned my_rank = this->communicator_pt()->my_rank();
43114 std::map<unsigned, unsigned> shd_bnd_over_int_bnd =
43115 this->Shared_boundary_overlaps_internal_boundary;
43119 std::set<unsigned> internal_boundary_overlaped;
43123 if (outfile.is_open())
43125 const unsigned nbound = this->nboundary();
43126 outfile <<
"Number of boundaries: " << nbound <<
"\n\n";
43127 outfile <<
"Number of elements and nodes associated to each "
43128 <<
"boundary before\nfilling elements and nodes\n\n";
43129 for (
unsigned i = 0; i < nbound; i++)
43131 outfile <<
"Boundary (" << i <<
") Elements ("
43132 << this->nboundary_element(i) <<
") " <<
"Nodes ("
43133 << this->nboundary_node(i) <<
")\n";
43138 std::set<unsigned> shared_boundaries_in_this_processor;
43142 for (
unsigned iproc = 0; iproc < nproc; iproc++)
43145 if (iproc != my_rank)
43148 unsigned nshared_boundaries_with_iproc =
43149 this->nshared_boundaries(my_rank, iproc);
43151 if (nshared_boundaries_with_iproc > 0)
43154 Vector<unsigned> bound_shared_with_iproc;
43155 bound_shared_with_iproc = this->shared_boundaries_ids(my_rank,
43159 for (
unsigned bs = 0; bs < nshared_boundaries_with_iproc; bs++)
43161 unsigned bnd_id = bound_shared_with_iproc[bs];
43162 shared_boundaries_in_this_processor.insert(bnd_id);
43173 for (std::map<unsigned, unsigned>::iterator it =
43174 shd_bnd_over_int_bnd.begin(); it != shd_bnd_over_int_bnd.end(); it++)
43177 const unsigned shd_bnd_id = (*it).first;
43179 const unsigned int_bnd_id = (*it).second;
43182 std::set<unsigned>::iterator it_set =
43183 shared_boundaries_in_this_processor.find(shd_bnd_id);
43184 if (it_set != shared_boundaries_in_this_processor.end())
43186 internal_boundary_overlaped.insert(int_bnd_id);
43191 const unsigned nbnd_node_shd_bnd = this->nboundary_node(shd_bnd_id);
43195 if (outfile.is_open())
43197 outfile <<
"\nPass info. from shared (" << shd_bnd_id
43198 <<
") to internal (" << int_bnd_id <<
")\n";
43199 outfile <<
"Number of shared boundary nodes: "
43200 << nbnd_node_shd_bnd <<
"\n";
43203 for (
unsigned in = 0; in < nbnd_node_shd_bnd; in++)
43206 Node* bnd_node_pt = this->boundary_node_pt(shd_bnd_id, in);
43208 this->add_boundary_node(int_bnd_id, bnd_node_pt);
43215 const unsigned nbnd_ele_shd_bnd = this->nboundary_element(shd_bnd_id);
43219 if (outfile.is_open())
43221 outfile <<
"Number of shared boundary elements: "
43222 << nbnd_ele_shd_bnd <<
"\n\n";
43227 for (
unsigned ie = 0; ie < nbnd_ele_shd_bnd; ie++)
43230 FiniteElement* bnd_ele_pt = this->boundary_element_pt(shd_bnd_id, ie);
43233 Boundary_element_pt[int_bnd_id].push_back(bnd_ele_pt);
43235 int face_index = this->face_index_at_boundary(shd_bnd_id, ie);
43237 Face_index_at_boundary[int_bnd_id].push_back(face_index);
43242 const unsigned nregions = this->nregion();
43245 for (
unsigned ir = 0 ; ir < nregions; ir++)
43248 const unsigned region_id =
43249 static_cast<unsigned>(this->Region_attribute[ir]);
43252 const unsigned nele_ir = this->nboundary_element_in_region(shd_bnd_id,
43254 for (
unsigned ier = 0; ier < nele_ir; ier++)
43257 FiniteElement* bnd_ele_pt =
43258 this->boundary_element_in_region_pt(shd_bnd_id, region_id, ier);
43261 this->Boundary_region_element_pt[int_bnd_id][region_id].
43262 push_back(bnd_ele_pt);
43266 this->face_index_at_boundary_in_region(shd_bnd_id, region_id, ier);
43268 this->Face_index_region_at_boundary[int_bnd_id][region_id].
43269 push_back(face_index);
43283 if (outfile.is_open())
43285 const unsigned nbound = this->nboundary();
43286 outfile <<
"Number of boundaries: " << nbound <<
"\n\n";
43287 outfile <<
"Number of elements and nodes associated to each "
43288 <<
"boundary after\nfilling elements and nodes\n\n";
43289 for (
unsigned i = 0; i < nbound; i++)
43291 outfile <<
"Boundary (" << i <<
") Elements ("
43292 << this->nboundary_element(i) <<
")" <<
" Nodes ("
43293 << this->nboundary_node(i) <<
")\n";
43301 for (std::set<unsigned>::iterator it = internal_boundary_overlaped.begin();
43302 it != internal_boundary_overlaped.end(); it++)
43304 const unsigned overlaped_internal_bnd_id = (*it);
43307 this->
template setup_boundary_coordinates<ELEMENT>(overlaped_internal_bnd_id);
43312 #endif // #ifdef OOMPH_HAS_MPI
43317 template <
class ELEMENT>
43323 if (!Boundary_coordinate_exists[b])
43339 std::set<Node*> tmp_boundary_node_pt;
43340 const unsigned nboundary_ele = this->nboundary_element(b);
43341 for (
unsigned e = 0; e < nboundary_ele; e++)
43344 FiniteElement* bulk_ele_pt = this->boundary_element_pt(b, e);
43345 #ifdef OOMPH_HAS_MPI
43347 if (!bulk_ele_pt->is_halo())
43351 int face_index = this->face_index_at_boundary(b, e);
43353 FiniteElement* face_ele_pt =
new DummyFaceElement<ELEMENT> (
43354 bulk_ele_pt, face_index);
43357 const unsigned nnodes = face_ele_pt->nnode();
43358 for (
unsigned i = 0; i < nnodes; i++)
43361 Node* tmp_node_pt = face_ele_pt->node_pt(i);
43363 tmp_boundary_node_pt.insert(tmp_node_pt);
43367 delete face_ele_pt;
43369 #ifdef OOMPH_HAS_MPI
43376 const unsigned long n_boundary_node = tmp_boundary_node_pt.size();
43379 if (n_boundary_node==0)
43381 #ifdef OOMPH_HAS_MPI
43383 if (!this->is_mesh_distributed())
43387 #ifdef OOMPH_HAS_MPI
43392 Mesh* face_mesh_pt =
new Mesh();
43393 create_unsorted_face_mesh_representation(b, face_mesh_pt);
43394 MeshAsGeomObject* mesh_geom_obj_pt =
new MeshAsGeomObject(face_mesh_pt);
43397 delete mesh_geom_obj_pt;
43401 face_mesh_pt->flush_node_storage();
43402 delete face_mesh_pt;
43410 Vector<double> node_coord(3);
43411 Vector<double> b_coord(1);
43413 Vector<Vector<double> > old_boundary_node(n_boundary_node);
43414 unsigned tmp_counter = 0;
43415 for(std::set<Node*>::iterator it_node = tmp_boundary_node_pt.begin();
43416 it_node != tmp_boundary_node_pt.end(); it_node++, tmp_counter++)
43418 Node* nod_pt = (*it_node);
43419 nod_pt->get_coordinates_on_boundary(b,b_coord);
43420 node_coord[0] = b_coord[0];
43421 node_coord[1] = nod_pt->x(0);
43422 node_coord[2] = nod_pt->x(1);
43423 old_boundary_node[tmp_counter] = node_coord;
43427 std::sort(old_boundary_node.begin(),old_boundary_node.end());
43436 Vector<Vector<Node*> > segment_nodes_pt;
43438 #ifdef OOMPH_HAS_MPI
43440 const unsigned nsegments = new_mesh_pt->nboundary_segment(b);
43444 const unsigned nsegments = 1;
43445 #endif // #ifdef OOMPH_HAS_MPI
43447 #ifdef OOMPH_HAS_MPI
43449 const unsigned n_new_boundary_node = new_mesh_pt->nboundary_segment_node(b);
43452 if (this->is_mesh_distributed())
43457 if (n_new_boundary_node==0)
43460 Mesh* face_mesh_pt =
new Mesh();
43461 create_unsorted_face_mesh_representation(b, face_mesh_pt);
43462 MeshAsGeomObject* mesh_geom_obj_pt =
new MeshAsGeomObject(face_mesh_pt);
43465 delete mesh_geom_obj_pt;
43468 face_mesh_pt->flush_node_storage();
43469 delete face_mesh_pt;
43473 #endif // #ifdef OOMPH_HAS_MPI
43476 Vector<Vector<unsigned> > nodes_to_be_snapped(nsegments);
43480 for (
unsigned is = 0;
is < nsegments;
is++)
43482 #ifdef OOMPH_HAS_MPI
43483 const unsigned n_new_boundary_segment_node =
43484 new_mesh_pt->nboundary_segment_node(b,
is);
43486 const unsigned n_new_boundary_segment_node = new_mesh_pt->nboundary_node(b);
43487 #endif // #ifdef OOMPH_HAS_MPI
43489 Vector<Vector<double> > new_boundary_node(n_new_boundary_segment_node);
43491 node_coord.resize(6,0.0);
43492 for(
unsigned n = 0; n < n_new_boundary_segment_node; n++)
43494 #ifdef OOMPH_HAS_MPI
43497 Node* nod_pt = new_mesh_pt->boundary_node_pt(b,n);
43498 #endif // #ifdef OOMPH_HAS_MPI
43499 nod_pt->get_coordinates_on_boundary(b,b_coord);
43500 node_coord[0] = b_coord[0];
43501 node_coord[1] = nod_pt->x(0);
43502 node_coord[2] = nod_pt->x(1);
43504 new_boundary_node[n] = node_coord;
43508 std::sort(new_boundary_node.begin(),new_boundary_node.end());
43515 unsigned old_index = 0;
43516 for(
unsigned n=0;n<n_new_boundary_segment_node;++n)
43520 for(
unsigned m=old_index;m<n_boundary_node;++m)
43523 (std::fabs(old_boundary_node[m][1]-new_boundary_node[n][1])<1.0e-14)
43525 (std::fabs(old_boundary_node[m][2]-new_boundary_node[n][2])<1.0e-14))
43528 new_boundary_node[n][4] = old_boundary_node[m][0];
43530 new_boundary_node[n][5] = 1.0;
43541 if((new_boundary_node[0][5]==0.0) ||
43542 (new_boundary_node[n_new_boundary_segment_node-1][5] == 0.0))
43544 std::ostringstream error_stream;
43546 <<
"New boundary coordinates not found for the first and/or last "
43548 <<
"on the boundary " << b <<
". This should not happen because "
43549 <<
"these\nlimits should have been setup in the constructor\n";
43551 <<
"The distance between the new and old nodes is probably outside\n"
43552 <<
"our tolerance.\n";
43553 error_stream.precision(20);
43554 error_stream <<
"Old boundaries: \n";
43556 old_boundary_node[0][1] <<
" " << old_boundary_node[0][2]
43558 old_boundary_node[n_boundary_node-1][1] <<
" " <<
43559 old_boundary_node[n_boundary_node-1][2] <<
"\n";
43560 error_stream <<
"New boundaries: \n" <<
43561 new_boundary_node[0][1] <<
" " << new_boundary_node[0][2] <<
" : " <<
43562 new_boundary_node[n_new_boundary_segment_node-1][1] <<
" " <<
43563 new_boundary_node[n_new_boundary_segment_node-1][2] <<
"\n";
43564 OomphLibWarning(error_stream.str(),
43565 "RefineableTriangleMesh::snap_nodes_onto_boundary()",
43566 OOMPH_EXCEPTION_LOCATION);
43572 if (!this->is_mesh_distributed())
43576 new_boundary_node[0][4] = new_boundary_node[0][0];
43579 new_boundary_node[n_new_boundary_segment_node-1][4] =
43580 new_boundary_node[0][5] = 1.0;
43582 new_boundary_node[n_new_boundary_segment_node-1][4] =
43583 new_boundary_node[n_new_boundary_segment_node-1][0];
43584 new_boundary_node[n_new_boundary_segment_node-1][5] = 1.0;
43589 for(
unsigned n=1;n<n_new_boundary_segment_node-1;++n)
43592 if(new_boundary_node[n][5]==0.0)
43595 nodes_to_be_snapped[
is].push_back(
43596 static_cast<unsigned>(new_boundary_node[n][3]));
43600 double zeta_old_low = new_boundary_node[n-1][0];
43601 double zeta_new_low = new_boundary_node[n-1][4];
43605 for(
unsigned m=n+1;m<n_new_boundary_segment_node;++m)
43607 if(new_boundary_node[m][5]==1.0)
43610 double zeta_old_high = new_boundary_node[m][0];
43611 double zeta_new_high = new_boundary_node[m][4];
43613 double frac = (new_boundary_node[n][0] - zeta_old_low)/
43614 (zeta_old_high - zeta_old_low);
43615 new_boundary_node[n][4] = zeta_new_low
43616 + frac*(zeta_new_high - zeta_new_low);
43617 new_boundary_node[n][5] = 1.0;
43625 for(
unsigned n=0;n<n_new_boundary_segment_node;++n)
43627 if(new_boundary_node[n][5]==0)
43629 throw OomphLibError(
43630 "New boundary coordinate not assigned\n",
43631 "RefineableTriangleMesh::snap_nodes_onto_boundary()",
43632 OOMPH_EXCEPTION_LOCATION);
43635 #ifdef OOMPH_HAS_MPI
43638 b,
is,
static_cast<unsigned>(new_boundary_node[n][3]))
43639 ->get_coordinates_on_boundary(b,b_coord);
43641 b_coord[0] = new_boundary_node[n][4];
43643 b,
is,
static_cast<unsigned>(new_boundary_node[n][3]))
43644 ->set_coordinates_on_boundary(b,b_coord);
43647 new_mesh_pt->boundary_node_pt(
43648 b,
static_cast<unsigned>(new_boundary_node[n][3]))
43649 ->get_coordinates_on_boundary(b,b_coord);
43651 b_coord[0] = new_boundary_node[n][4];
43652 new_mesh_pt->boundary_node_pt(
43653 b,
static_cast<unsigned>(new_boundary_node[n][3]))
43654 ->set_coordinates_on_boundary(b,b_coord);
43655 #endif // #ifdef OOMPH_HAS_MPI
43661 Mesh* face_mesh_pt =
new Mesh();
43662 create_unsorted_face_mesh_representation(b, face_mesh_pt);
43665 MeshAsGeomObject* mesh_geom_obj_pt=
new MeshAsGeomObject(face_mesh_pt);
43669 Vector<double> new_x(2);
43672 for(
unsigned is = 0;
is < nsegments;
is++)
43674 const unsigned nnodes_to_snap = nodes_to_be_snapped[
is].size();
43676 for (
unsigned in = 0; in < nnodes_to_snap; in++)
43679 unsigned n = nodes_to_be_snapped[
is][in];
43680 #ifdef OOMPH_HAS_MPI
43685 Node*
const nod_pt = new_mesh_pt->boundary_node_pt(b,n);
43686 #endif // #ifdef OOMPH_HAS_MPI
43688 nod_pt->get_coordinates_on_boundary(b,b_coord);
43690 mesh_geom_obj_pt->position(b_coord,new_x);
43693 for(
unsigned i=0;i<2;i++)
43695 nod_pt->x(i) = new_x[i];
43701 delete mesh_geom_obj_pt;
43704 face_mesh_pt->flush_node_storage();
43705 delete face_mesh_pt;
43711 TElement<2,3> dummy_six_node_element;
43712 for (
unsigned j=0;j<6;j++)
43714 dummy_six_node_element.construct_node(j);
43719 unsigned n_bound_el = new_mesh_pt->nboundary_element(b);
43720 for(
unsigned e=0;e<n_bound_el;e++)
43722 FiniteElement* el_pt = new_mesh_pt->boundary_element_pt(b,e);
43725 unsigned nnod=el_pt->nnode();
43737 TElement<2,2>* t_el_pt=
dynamic_cast<TElement<2,2>*
>(el_pt);
43740 throw OomphLibError(
43741 "Have a three-noded element that's not a TElement<2,2>",
43742 OOMPH_CURRENT_FUNCTION,
43743 OOMPH_EXCEPTION_LOCATION);
43751 else if ((nnod==6)||(nnod==7))
43756 TElement<2,3>* t_el_pt=
dynamic_cast<TElement<2,3>*
>(el_pt);
43761 throw OomphLibError(
43762 "Have a six-noded element that's not a TElement<2,3>",
43763 OOMPH_CURRENT_FUNCTION,
43764 OOMPH_EXCEPTION_LOCATION);
43768 throw OomphLibError(
43769 "Have a seven-noded element that's not a TElement<2,3>",
43770 OOMPH_CURRENT_FUNCTION,
43771 OOMPH_EXCEPTION_LOCATION);
43784 if(el_pt->node_pt(3)->is_on_boundary(b))
43788 if(!el_pt->node_pt(5)->is_on_boundary())
43791 for(
unsigned i=0;i<2;i++)
43793 el_pt->node_pt(5)->x(i) =
43794 0.5*(el_pt->node_pt(0)->x(i) + el_pt->node_pt(2)->x(i));
43799 if(!el_pt->node_pt(4)->is_on_boundary())
43802 for(
unsigned i=0;i<2;i++)
43804 el_pt->node_pt(4)->x(i) =
43805 0.5*(el_pt->node_pt(1)->x(i) + el_pt->node_pt(2)->x(i));
43811 if(el_pt->node_pt(4)->is_on_boundary(b))
43815 if(!el_pt->node_pt(5)->is_on_boundary())
43818 for(
unsigned i=0;i<2;i++)
43820 el_pt->node_pt(5)->x(i) =
43821 0.5*(el_pt->node_pt(0)->x(i) + el_pt->node_pt(2)->x(i));
43826 if(!el_pt->node_pt(3)->is_on_boundary())
43829 for(
unsigned i=0;i<2;i++)
43831 el_pt->node_pt(3)->x(i) =
43832 0.5*(el_pt->node_pt(0)->x(i) + el_pt->node_pt(1)->x(i));
43838 if(el_pt->node_pt(5)->is_on_boundary(b))
43842 if(!el_pt->node_pt(4)->is_on_boundary())
43845 for(
unsigned i=0;i<2;i++)
43847 el_pt->node_pt(4)->x(i) =
43848 0.5*(el_pt->node_pt(1)->x(i) + el_pt->node_pt(2)->x(i));
43853 if(!el_pt->node_pt(3)->is_on_boundary())
43856 for(
unsigned i=0;i<2;i++)
43858 el_pt->node_pt(3)->x(i) =
43859 0.5*(el_pt->node_pt(0)->x(i) + el_pt->node_pt(1)->x(i));
43869 TBubbleEnrichedElement<2,3>* t_el_pt=
43870 dynamic_cast<TBubbleEnrichedElement<2,3>*
>(el_pt);
43873 throw OomphLibError(
43874 "Have seven-noded element that's not a TBubbleEnrichedElement<2,3>",
43875 OOMPH_CURRENT_FUNCTION,
43876 OOMPH_EXCEPTION_LOCATION);
43880 for (
unsigned j=0;j<6;j++)
43882 for (
unsigned i=0;i<2;i++)
43884 dummy_six_node_element.node_pt(j)->x(i)=el_pt->node_pt(j)->x(i);
43889 unsigned j_enriched=6;
43890 Vector<double>
s(2);
43891 el_pt->local_coordinate_of_node(j_enriched,
s);
43894 Vector<double> x(2);
43895 dummy_six_node_element.interpolated_x(
s,x);
43896 el_pt->node_pt(j_enriched)->x(0) = x[0];
43897 el_pt->node_pt(j_enriched)->x(1) = x[1];
43904 std::ostringstream error_stream;
43906 <<
"Cannot deal with this particular " << nnod
43907 <<
"-noded element yet.\n"
43908 <<
"Please implement this yourself.\n";
43909 throw OomphLibError(error_stream.str(),
43910 OOMPH_CURRENT_FUNCTION,
43911 OOMPH_EXCEPTION_LOCATION);
43916 for (
unsigned j=0;j<6;j++)
43918 delete dummy_six_node_element.node_pt(j);
43925 #endif // #ifdef OOMPH_HAS_TRIANGLE_LIB